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

Importante

Questo documento è stato sostituito dal documento di riferimento Gestione delle funzionalità .NET, che fornisce la più recente e dettagliata rundown delle funzionalità disponibili nelle librerie di gestione delle funzionalità .NET.

Per iniziare a usare i flag di funzionalità nelle app, seguire gli avvii rapidi per le app console .NET o le app ASP.NET Core.

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

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 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à.

Prerequisiti

  • L’avvio rapido Aggiungere flag di funzionalità a un'app ASP.NET Core mostra un modo semplice di usare 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 nell’avvio rapido per provare il codice di esempio illustrato in questa esercitazione.

Configurare la gestione delle funzionalità

Per accedere al manager delle funzionalità .NET, l'app deve avere riferimenti ai pacchetti NuGet Microsoft.Azure.AppConfiguration.AspNetCore e Microsoft.FeatureManagement.AspNetCore.

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

Per impostazione predefinita, il manager di funzionalità recupera la configurazione dei flag di funzionalità dalla sezione "FeatureManagement" dei dati di configurazione di .NET. Per usare la posizione di configurazione predefinita, chiamare il metodo AddFeatureManagement del 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"));

È possibile usare filtri di funzionalità per abilitare i flag di funzionalità condizionali. Per usare i filtri di funzionalità predefiniti o crearne di personalizzati, vedere Abilitare le funzionalità condizionali con filtri delle funzionalità.

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 di Azure offre un'interfaccia utente del portale dedicata per la gestione di tutti i flag di funzionalità. Il servizio di Configurazione app di Azure fornisce anche i flag di funzionalità dell’applicazione direttamente attraverso le relative librerie client .NET.

Il modo più semplice per connettere l'applicazione ASP.NET Core a Configurazione app di Azure è tramite il provider di configurazione incluso nel pacchetto NuGet Microsoft.Azure.AppConfiguration.AspNetCore. Dopo aver incluso un riferimento al pacchetto, seguire questa procedura per usare il 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 classe program.cs, registrare i servizi e il middleware di Configurazione app di Azure negli oggetti builder 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 di 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 mostra come modificare l’orario di scadenza della cache o l'intervallo di polling 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à è costituita da due parti: un nome e un elenco di uno o più filtri che consentono di valutare se lo stato di una funzionalità è attivo (ovvero, quando il relativo valore è True). Un filtro definisce un criterio per il quale 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:

  • FeatureA è attivo.
  • FeatureB è disattivato.
  • FeatureC specifica un filtro denominato Percentage con una proprietà Parameters. Percentage è un filtro configurabile. In questo esempio Percentage specifica una probabilità del 50% che il flag FeatureC sia attivo. Per una guida pratica sull'uso dei filtri delle funzionalità, vedere Usare filtri di funzionalità per abilitare i flag di funzionalità condizionali.

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 MVC di ASP.NET Core è possibile accedere al manager di funzionalità IFeatureManager grazie all'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 dispone già di 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 a cui fa riferimento il 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à

Il criterio comune di gestione delle funzionalità consiste nel controllare se un flag di funzionalità è impostato su attivo e in tal caso 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 è stata 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: