Esercitazione: Usare i flag di funzionalità in un'app ASP.NET Core

Le librerie di gestione delle funzionalità .NET offrono supporto idiomatico per l'implementazione di flag di funzionalità in un'applicazione .NET o ASP.NET Core. Queste librerie consentono di aggiungere in modo dichiarativo flag di funzionalità al codice in modo che non sia necessario scrivere manualmente codice per abilitare o disabilitare le funzionalità con if istruzioni .

Le librerie di gestione delle funzionalità gestiscono anche i cicli di vita dei flag di funzionalità in background. Ad esempio, le librerie aggiornano e memorizzano nella cache gli stati del flag o garantiscono lo stato immutabile di un flag durante una chiamata di richiesta. In aggiunta, la libreria ASP.NET Core offre integrazioni predefinite, tra cui le azioni del controller MVC, viste, route e middleware.

La guida introduttiva Aggiungere flag di funzionalità a un'app ASP.NET Core illustra un semplice esempio di come usare i flag di funzionalità in un'applicazione ASP.NET Core. Questa esercitazione illustra opzioni di configurazione e funzionalità aggiuntive delle librerie di Gestione funzionalità. È possibile usare l'app di esempio creata nella guida introduttiva per provare il codice di esempio illustrato in questa esercitazione.

Per la documentazione di riferimento dell'API di gestione delle funzionalità di base di ASP.NET, vedere Spazio dei nomi Microsoft.FeatureManagement.

La presente esercitazione include informazioni su come:

  • Aggiungere i flag di funzionalità nelle parti chiave dell'applicazione per controllare la disponibilità delle funzionalità.
  • Eseguire l'integrazione con Configurazione app quando viene usato per gestire i flag di funzionalità.

Configurare la gestione delle funzionalità

Per accedere a .NET Feature Manager, l'app deve avere riferimenti ai Microsoft.Azure.AppConfiguration.AspNetCore pacchetti NuGet e Microsoft.FeatureManagement.AspNetCore .

Gestione funzionalità .NET viene configurato dal sistema di configurazione nativo del framework. Di conseguenza, è possibile definire le impostazioni del flag di funzionalità dell'applicazione usando qualsiasi origine di configurazione supportata da .NET, incluso il file locale appsettings.json o le variabili di ambiente.

Per impostazione predefinita, gestione funzionalità recupera la configurazione del flag di funzionalità dalla "FeatureManagement" sezione dei dati di configurazione di .NET Core. Per usare il percorso di configurazione predefinito, chiamare il metodo AddFeatureManagement di IServiceCollection passato al metodo ConfigureServices della classe Startup .

using Microsoft.FeatureManagement;

builder.Services.AddFeatureManagement();

È possibile specificare che la configurazione di gestione delle funzionalità deve essere recuperata da una sezione di configurazione diversa chiamando Configuration.GetSection e passando il nome della sezione desiderata. L'esempio seguente indica invece la lettura da un'altra sezione chiamata "MyFeatureFlags":

using Microsoft.FeatureManagement;

builder.Services.AddFeatureManagement(Configuration.GetSection("MyFeatureFlags"));

Se si usano filtri nei flag di funzionalità, è necessario includere lo spazio dei nomi Microsoft.FeatureManagement.FeatureFilters e aggiungere una chiamata a AddFeatureFilter specificando il nome del tipo del filtro da usare come tipo generico del metodo. Per altre informazioni sull'uso dei filtri delle funzionalità per abilitare e disabilitare in modo dinamico la funzionalità, vedere Abilitare l'implementazione a fasi delle funzionalità per i destinatari di destinazione.

L'esempio seguente illustra come usare un filtro di funzionalità incorporato denominato PercentageFilter:

using Microsoft.FeatureManagement;

builder.Services.AddFeatureManagement()
    .AddFeatureFilter<PercentageFilter>();

Invece di impostare come hardcoded i flag di funzionalità nell'applicazione, è consigliabile mantenere i flag di funzionalità all'esterno dell'applicazione e gestirli separatamente. In questo modo è possibile modificare gli stati dei flag in qualsiasi momento e applicare immediatamente tali modifiche nell'applicazione. Il servizio di configurazione app Azure offre un'interfaccia utente del portale dedicata per la gestione di tutti i flag di funzionalità. Il servizio di configurazione app Azure fornisce anche i flag di funzionalità all'applicazione direttamente tramite le librerie client .NET Core.

Il modo più semplice per connettere l'applicazione ASP.NET Core a Configurazione app consiste nel provider di configurazione incluso nel Microsoft.Azure.AppConfiguration.AspNetCore pacchetto NuGet. Dopo aver incluso un riferimento al pacchetto, seguire questa procedura per usare questo pacchetto NuGet.

  1. Aprire il file Program.cs e aggiungere il codice seguente.

    using Microsoft.Extensions.Configuration.AzureAppConfiguration;
    
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Configuration.AddAzureAppConfiguration(options =>
        options.Connect(
            builder.Configuration["ConnectionStrings:AppConfig"])
            .UseFeatureFlags());
    
  2. Aggiornare le configurazioni del middleware e del servizio per l'app usando il codice seguente.

    All'interno della program.cs classe registrare i servizi di configurazione app Azure e il middleware negli builder oggetti e app :

    builder.Services.AddAzureAppConfiguration();
    
    app.UseAzureAppConfiguration();
    

In uno scenario tipico si aggiorneranno periodicamente i valori dei flag di funzionalità durante la distribuzione e l'abilitazione e le diverse funzionalità dell'applicazione. Per impostazione predefinita, i valori dei flag di funzionalità vengono memorizzati nella cache per un periodo di 30 secondi, in modo che un'operazione di aggiornamento attivata quando il middleware riceve la richiesta non aggiorni il valore fino alla scadenza del valore memorizzato nella cache. Il codice seguente illustra come modificare l'intervallo di scadenza o di polling della cache su 5 minuti impostando CacheExpirationInterval nella chiamata a UseFeatureFlags.

config.AddAzureAppConfiguration(options =>
    options.Connect(
        builder.Configuration["ConnectionStrings:AppConfig"])
            .UseFeatureFlags(featureFlagOptions => {
                featureFlagOptions.CacheExpirationInterval = TimeSpan.FromMinutes(5);
    }));

Dichiarazione del flag di funzionalità

Ogni dichiarazione di flag di funzionalità ha due parti: un nome e un elenco di uno o più filtri usati per valutare se lo stato di una funzionalità è attivo , ovvero quando il relativo valore è True. Un filtro definisce un criterio per il momento in cui deve essere attivata una funzionalità.

Quando un flag di funzionalità include più filtri, l'elenco dei filtri viene scorso nell'ordine fino a quando uno dei filtri non determina che la funzionalità deve essere abilitata. A questo punto, il flag di funzionalità è attivo e i risultati del filtro rimanenti vengono ignorati. Se nessun filtro indica che deve essere abilitata la funzionalità, il flag di funzionalità viene disattivato.

La gestione funzionalità supporta appsettings.json come origine configurazione per i flag di funzionalità. L'esempio seguente mostra come configurare i flag di funzionalità in un file JSON:

{"FeatureManagement": {
        "FeatureA": true, // Feature flag set to on
        "FeatureB": false, // Feature flag set to off
        "FeatureC": {
            "EnabledFor": [
                {
                    "Name": "Percentage",
                    "Parameters": {
                        "Value": 50
                    }
                }
            ]
        }
    }
}

Per convenzione, la sezione FeatureManagement di questo documento JSON viene usata per le impostazioni dei flag di funzionalità. L'esempio precedente mostra tre flag di funzionalità con i relativi filtri definiti nella proprietà EnabledFor:

Usare l'inserimento delle dipendenze per accedere a IFeatureManager

Per alcune operazioni, ad esempio il controllo manuale dei valori dei flag di funzionalità, è necessario ottenere un'istanza di IFeatureManager. In ASP.NET Core MVC è possibile accedere al gestore IFeatureManager delle funzionalità tramite l'inserimento delle dipendenze. Nell'esempio seguente viene aggiunto un argomento di tipo IFeatureManager alla firma del costruttore per un controller. Il runtime risolve automaticamente il riferimento e fornisce un'implementazione dell'interfaccia quando si chiama il costruttore. Se si usa un modello di applicazione in cui il controller ha già uno o più argomenti di inserimento delle dipendenze nel costruttore, ad esempio ILogger, è sufficiente aggiungere IFeatureManager come argomento aggiuntivo:

using Microsoft.FeatureManagement;

public class HomeController : Controller
{
    private readonly IFeatureManager _featureManager;

    public HomeController(ILogger<HomeController> logger, IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }
}

Riferimenti di flag funzionalità

Definire i flag di funzionalità come variabili stringa per farvi riferimento dal codice:

public static class MyFeatureFlags
{
    public const string FeatureA = "FeatureA";
    public const string FeatureB = "FeatureB";
    public const string FeatureC = "FeatureC";
}

Controlli dei flag di funzionalità

Un modello comune di gestione delle funzionalità consiste nel verificare se un flag di funzionalità è impostato su on e, in caso affermativo, eseguire una sezione di codice. Ad esempio:

IFeatureManager featureManager;
...
if (await featureManager.IsEnabledAsync(MyFeatureFlags.FeatureA))
{
    // Run the following code
}

Azioni del controller

Con i controller MVC, è possibile usare l'attributo FeatureGate per controllare se è abilitata un'intera classe controller o un'azione specifica. Il controller HomeController seguente richiede che il flag FeatureA sia attivo prima che venga eseguita qualsiasi azione contenuta nella classe controller:

using Microsoft.FeatureManagement.Mvc;

[FeatureGate(MyFeatureFlags.FeatureA)]
public class HomeController : Controller
{
    ...
}

Per poter eseguire l'azione Index seguente, il flagFeatureA deve essere attivo:

using Microsoft.FeatureManagement.Mvc;

[FeatureGate(MyFeatureFlags.FeatureA)]
public IActionResult Index()
{
    return View();
}

Quando un controller O un'azione MVC viene bloccata perché il flag di funzionalità di controllo è disattivato, viene chiamata un'interfaccia IDisabledFeaturesHandler registrata. L'interfaccia IDisabledFeaturesHandler predefinita restituisce un codice di stato 404 al client senza alcun corpo della risposta.

Viste MVC

Aprire _ViewImports.cshtml nella directory Views e aggiungere l'helper per i tag di gestione funzionalità:

@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

Nelle viste MVC è possibile usare un tag <feature> per eseguire il rendering del contenuto in base allo stato di attivazione del flag di funzionalità:

<feature name="FeatureA">
    <p>This can only be seen if 'FeatureA' is enabled.</p>
</feature>

Per visualizzare il contenuto alternativo quando non vengono soddisfatti i requisiti, può essere utilizzato l'attributo negate.

<feature name="FeatureA" negate="true">
    <p>This will be shown if 'FeatureA' is disabled.</p>
</feature>

Il tag di funzionalità <feature> può anche essere usato per mostrare il contenuto se una o tutte le funzionalità di un elenco sono abilitate.

<feature name="FeatureA, FeatureB" requirement="All">
    <p>This can only be seen if 'FeatureA' and 'FeatureB' are enabled.</p>
</feature>
<feature name="FeatureA, FeatureB" requirement="Any">
    <p>This can be seen if 'FeatureA', 'FeatureB', or both are enabled.</p>
</feature>

Filtri MVC

È possibile configurare i filtri MVC in modo da attivarli in base allo stato di un flag di funzionalità. Questa funzionalità è limitata ai filtri che implementano IAsyncActionFilter. Il codice seguente aggiunge un filtro MVC denominato ThirdPartyActionFilter. Questo filtro viene attivato all'interno della pipeline MVC solo se il flag FeatureA è attivato.

using Microsoft.FeatureManagement.FeatureFilters;

IConfiguration Configuration { get; set;}

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options => {
        options.Filters.AddForFeature<ThirdPartyActionFilter>(MyFeatureFlags.FeatureA);
    });
}

Middleware

È possibile usare i flag di funzionalità per aggiungere rami di applicazioni e middleware in modo condizionale. Il codice seguente inserisce un componente middleware nella pipeline di richiesta solo quando il flag FeatureA è attivato:

app.UseMiddlewareForFeature<ThirdPartyMiddleware>(MyFeatureFlags.FeatureA);

Questo codice produce la capacità più generica di creare rami nell'intera applicazione in base al flag di funzionalità:

app.UseForFeature(featureName, appBuilder => {
    appBuilder.UseMiddleware<T>();
});

Passaggi successivi

In questa esercitazione si è appreso come implementare i flag di funzionalità nell'applicazione ASP.NET Core usando le librerie Microsoft.FeatureManagement. Per altre informazioni sul supporto della gestione funzionalità in ASP.NET Core e Configurazione app, vedere le risorse seguenti: