Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La libreria di gestione delle funzionalità .NET consente di sviluppare ed esporre funzionalità dell'applicazione in base ai flag di funzionalità. Quando viene sviluppata una nuova funzionalità, molte applicazioni hanno requisiti speciali, ad esempio quando la funzionalità deve essere abilitata e in quali condizioni. Questa libreria consente di definire queste relazioni. Si integra anche con i modelli di codice .NET comuni per rendere possibile l'esposizione di queste funzionalità.
I flag di funzionalità consentono alle applicazioni .NET e ASP.NET Core di attivare o disattivare dinamicamente le funzionalità. È possibile usare i flag delle funzionalità in casi d'uso di base, come le istruzioni condizionali. È anche possibile usare flag di funzionalità in scenari più avanzati, ad esempio l'aggiunta condizionale di route o filtri MVC (Model-View-Controller). I flag di funzionalità si basano sul sistema di configurazione .NET Core. Qualsiasi provider di configurazione .NET Core è in grado di fungere da backbone per i flag di funzionalità.
Ecco alcuni dei vantaggi dell'uso della libreria di gestione delle funzionalità .NET:
- Usa convenzioni comuni per la gestione delle funzionalità.
- Ha una barriera bassa per l'ingresso:
- Si basa sull'interfaccia
IConfiguration. - Supporta la configurazione dei flag di funzionalità nei file JSON.
- Si basa sull'interfaccia
- Fornisce la gestione della durata dei flag di funzionalità.
- I valori di configurazione possono cambiare in tempo reale.
- I flag di funzionalità possono essere coerenti nell'intera richiesta.
- Vengono illustrati scenari di base e complessi offrendo il supporto per le funzionalità seguenti:
- Attivazione e disattivazione delle funzionalità tramite un file di configurazione dichiarativo
- Presentazione di varianti diverse di una funzionalità a utenti diversi
- Valutazione dinamica dello stato di una funzionalità in base a una chiamata a un server
- Fornisce estensioni API per ASP.NET Framework Core e MVC nelle aree seguenti:
- Routing.
- Filtri
- Attributi di azione
La libreria di gestione delle funzionalità .NET è open source. Per altre informazioni, vedere il repository GitHub FeatureManagement-Dotnet .
Indicatori di funzionalità
I flag di funzionalità possono essere abilitati o disabilitati. Lo stato di un flag può essere reso condizionale tramite filtri di funzionalità.
Filtri di funzionalità
I filtri di funzionalità definiscono uno scenario per il momento in cui è necessario abilitare una funzionalità. Per valutare lo stato di una funzionalità, il relativo elenco di filtri di funzionalità viene attraversato fino a quando uno dei filtri non determina l'abilitazione della funzionalità. A questo punto, l'attraversamento grafico attraverso i filtri di funzionalità si arresta. Se nessun filtro di funzionalità indica che la funzionalità deve essere abilitata, questa viene considerata disattivata.
Si supponga, ad esempio, di progettare un filtro di funzionalità del browser Microsoft Edge. Se una richiesta HTTP proviene da Microsoft Edge, il filtro delle funzionalità attiva tutte le funzionalità a cui è collegato.
Configurazione del flag di funzionalità
Il sistema di configurazione di .NET Core viene usato per determinare lo stato dei flag di funzionalità. La base di questo sistema è l'interfaccia IConfiguration . È possibile usare qualsiasi provider per IConfiguration come provider di stato della funzionalità per la libreria dei flag di funzionalità. Questo sistema supporta scenari che vanno dal file di configurazione appsettings.json a Configurazione app di Azure.
Dichiarazione dei flag di funzionalità
La libreria di gestione delle funzionalità supporta il file di configurazione appsettings.json come origine del flag di funzionalità perché è un provider per il sistema .NET Core IConfiguration . I flag di funzionalità vengono dichiarati utilizzando il Microsoft Feature Management schema. Questo schema è indipendente dal linguaggio di origine ed è supportato in tutte le librerie di gestione delle funzionalità Microsoft.
Il codice nell'esempio seguente dichiara i flag di funzionalità in un file JSON:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
// Define feature flags in a JSON file.
"feature_management": {
"feature_flags": [
{
"id": "FeatureT",
"enabled": false
},
{
"id": "FeatureU",
"enabled": true,
"conditions": {}
},
{
"id": "FeatureV",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Sun, 01 Jun 2025 13:59:59 GMT",
"End": "Fri, 01 Aug 2025 00:00:00 GMT"
}
}
]
}
}
]
}
}
La feature_management sezione del documento JSON viene usata per convenzione per caricare le impostazioni del flag di funzionalità. È necessario elencare gli oggetti flag di funzionalità nell'array feature_flags in questa sezione. Questo codice elenca tre flag di funzionalità. Ogni oggetto flag di funzionalità ha una proprietà id e una proprietà enabled.
- Il valore
idè il nome utilizzato per identificare il flag di funzionalità e farvi riferimento. - La proprietà
enabledspecifica lo stato abilitato del flag di funzionalità.
Una funzionalità è disattivata se enabled è false. Se enabled è true, lo stato della funzionalità dipende dalla proprietà conditions. La conditions proprietà dichiara le condizioni utilizzate per abilitare dinamicamente la funzionalità.
- Se un flag di funzionalità non ha una
conditionsproprietà, la funzionalità è attivata. - Se un flag di funzionalità ha una
conditionsproprietà e le relative condizioni vengono soddisfatte, la funzionalità è attivata. - Se un flag di funzionalità ha una
conditionsproprietà e le relative condizioni non vengono soddisfatte, la funzionalità è disattivata.
I filtri delle funzionalità sono definiti nella client_filters matrice. Nel codice precedente il FeatureV flag di funzionalità ha un filtro di funzionalità denominato Microsoft.TimeWindow. Questo filtro è un esempio di filtro di funzionalità configurabile. In questo codice, questo filtro ha una parameters proprietà . La proprietà viene utilizzata per configurare il filtro. In questo caso, vengono configurati gli orari di inizio e fine per la funzionalità da attivare.
Avanzate: il segno dei due punti (:) non è consentito nei nomi dei flag di funzionalità.
Requirement_type
All'interno della conditions proprietà viene utilizzata la requirement_type proprietà per determinare se i filtri devono usare Any o All la logica durante la valutazione dello stato di una funzionalità. Se requirement_type non è specificato, il valore predefinito è Any. I requirement_type valori comportano il comportamento seguente:
-
Any: È sufficiente che un solo filtro venga valutato atrueper abilitare la funzionalità. -
All: ogni filtro deve restituiretrueper abilitare la funzionalità.
Un requirement_type di All cambia il modo in cui vengono attraversati i filtri:
- Se non sono elencati filtri, la funzionalità è disabilitata.
- Se i filtri sono elencati, vengono attraversati fino a quando le condizioni di uno specificano che la funzionalità deve essere disabilitata. Se nessun filtro indica che la funzionalità deve essere disabilitata, questa viene considerata abilitata.
{
"id": "FeatureW",
"enabled": true,
"conditions": {
"requirement_type": "All",
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Sun, 01 Jun 2025 13:59:59 GMT",
"End": "Fri, 01 Aug 00:00:00 GMT"
}
},
{
"name": "Microsoft.Percentage",
"parameters": {
"Value": "50"
}
}
]
}
}
In questo esempio, il flag della funzionalità FeatureW ha un valore requirement_type di All. Di conseguenza, tutti i relativi filtri devono restituire true affinché la funzionalità sia abilitata. In questo caso, la funzionalità è abilitata per il 50% degli utenti durante l'intervallo di tempo specificato.
Gestione di più origini di configurazione
A partire dalla versione 4.3.0, è possibile acconsentire esplicitamente all'unione personalizzata per i flag di funzionalità dello schema Microsoft (la sezione feature_management). Quando lo stesso ID flag di funzionalità compare in più origini di configurazione, un'istanza della classe predefinita ConfigurationFeatureDefinitionProvider unisce tali definizioni in base all'ordine di registrazione del fornitore di configurazione. Se si verifica un conflitto, viene usata l'ultima definizione del flag di funzionalità. Questo comportamento è diverso dall'unione predefinita basata su indici di matrice in .NET.
Il codice seguente consente l'unione della configurazione del flag di funzionalità personalizzata tramite iniezione di dipendenze:
IConfiguration configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.prod.json")
.Build();
services.AddSingleton(configuration);
services.AddFeatureManagement();
services.Configure<ConfigurationFeatureDefinitionProviderOptions>(o =>
{
o.CustomConfigurationMergingEnabled = true;
});
È anche possibile abilitare l'unione personalizzata quando si costruisce un'istanza di ConfigurationFeatureDefinitionProvider:
var featureManager = new FeatureManager(
new ConfigurationFeatureDefinitionProvider(
configuration,
new ConfigurationFeatureDefinitionProviderOptions
{
CustomConfigurationMergingEnabled = true
}));
Comportamento di esempio:
// appsettings.json
{
"feature_management": {
"feature_flags": [
{ "id": "FeatureA", "enabled": true },
{ "id": "FeatureB", "enabled": false }
]
}
}
// appsettings.prod.json (added later in ConfigurationBuilder)
{
"feature_management": {
"feature_flags": [
{ "id": "FeatureB", "enabled": true }
]
}
}
Quando si abilita l'unione personalizzata, FeatureA rimane abilitata e FeatureB si imposta su abilitata, perché viene utilizzata l'ultima dichiarazione. Quando si usa l'unione .NET predefinita, in cui l'unione personalizzata è disabilitata, le matrici vengono unite per indice. Questo approccio può produrre risultati imprevisti se le origini non sono allineate in base alla posizione.
Schema di gestione delle funzionalità .NET
Nelle versioni precedenti della libreria di gestione delle funzionalità, lo schema primario era lo schema di gestione delle funzionalità .NET.
A partire dalla versione 4.0.0 della libreria, le nuove funzionalità, incluse le varianti e i dati di telemetria, non sono supportate nello schema di gestione delle funzionalità .NET.
Note
Se la configurazione del flag di funzionalità include una dichiarazione elencata nelle sezioni feature_management e FeatureManagement, quella della sezione feature_management viene adottata.
Consumo
In un'implementazione di base, la gestione delle funzionalità controlla se è abilitato un flag di funzionalità. Esegue quindi azioni in base al risultato. Questo controllo viene eseguito tramite il IsEnabledAsync metodo di IVariantFeatureManager.
…
IVariantFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
// Do something.
}
Registrazione del servizio
La gestione delle funzionalità si basa sull'inserimento delle dipendenze di .NET Core. Come illustrato nel codice seguente, è possibile usare le convenzioni standard per registrare i servizi di gestione delle funzionalità:
using Microsoft.FeatureManagement;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement();
}
}
Per impostazione predefinita, il gestore delle funzionalità recupera la configurazione del flag di funzionalità dalla sezione feature_management o FeatureManagement dei dati di configurazione di .NET Core. Se nessuna delle due sezioni esiste, la configurazione viene considerata vuota.
Note
È anche possibile specificare che la configurazione del flag di funzionalità deve essere recuperata da una sezione di configurazione diversa passando la sezione a AddFeatureManagement. Nell'esempio seguente viene specificato che il gestore delle funzionalità dovrebbe leggere da una sezione denominata MyFeatureFlags invece.
services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));
Inserimento delle dipendenze
Quando si usa la libreria di gestione delle funzionalità con MVC, è possibile ottenere l'oggetto che implementa IVariantFeatureManager usando l'inserimento delle dipendenze.
public class HomeController : Controller
{
private readonly IVariantFeatureManager _featureManager;
public HomeController(IVariantFeatureManager featureManager)
{
_featureManager = featureManager;
}
}
Servizi di gestione delle funzionalità con ambito definito
Il AddFeatureManagement metodo aggiunge i servizi di gestione delle funzionalità come singleton all'interno di un'applicazione. Alcuni scenari richiedono l'aggiunta di servizi di gestione delle funzionalità come servizi con un ambito definito. Ad esempio, è possibile usare filtri di funzionalità che utilizzano servizi con ambito per informazioni sul contesto. In questo caso, è necessario usare il AddScopedFeatureManagement metodo . Questo metodo garantisce che i servizi di gestione delle funzionalità, inclusi i filtri delle funzionalità, vengano aggiunti come servizi con ambito.
services.AddScopedFeatureManagement();
Integrazione ASP.NET Core
La libreria di gestione delle funzionalità offre funzionalità in ASP.NET Core e MVC per abilitare scenari comuni di flag di funzionalità nelle applicazioni Web. Queste funzionalità sono disponibili facendo riferimento al pacchetto NuGet Microsoft.FeatureManagement.AspNetCore.
Controller e azioni
Un controller MVC e le azioni possono richiedere l'abilitazione di una determinata funzionalità o di un elenco di funzionalità per l'esecuzione. È possibile soddisfare questo requisito usando un FeatureGateAttribute oggetto . La classe FeatureGateAttribute è definita nel namespace Microsoft.FeatureManagement.Mvc.
[FeatureGate("FeatureX")]
public class HomeController : Controller
{
…
}
Nell'esempio precedente la HomeController classe viene controllata da FeatureX.
HomeController le azioni possono essere eseguite solo se la FeatureX funzionalità è abilitata.
[FeatureGate("FeatureX")]
public IActionResult Index()
{
return View();
}
Nell'esempio precedente l'azione Index MVC può essere eseguita solo se la FeatureX funzionalità è abilitata.
Gestione delle azioni disabilitata
Quando un controller o un'azione MVC viene bloccata perché nessuna delle funzionalità specificate è abilitata, viene richiamata un'implementazione registrata di IDisabledFeaturesHandler . Per impostazione predefinita, viene registrato un gestore minimalista che restituisce un errore HTTP 404. È possibile sovrascrivere questo handler usando IFeatureManagementBuilder quando si registrano i flag delle funzionalità.
public interface IDisabledFeaturesHandler
{
Task HandleDisabledFeatures(IEnumerable<string> features, ActionExecutingContext context);
}
Visualizzazione
Nelle visualizzazioni MVC è possibile usare <feature> i tag per eseguire il rendering condizionale del contenuto. È possibile basare le condizioni di rendering su se una funzionalità è abilitata o se viene assegnata una variante specifica di una funzionalità. Per altre informazioni, vedere Varianti più avanti in questo articolo.
<feature name="FeatureX">
<p>This content appears only when 'FeatureX' is enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha">
<p>This content appears only when variant 'Alpha' of 'FeatureX' is assigned.</p>
</feature>
È anche possibile negare la valutazione dell'helper tag se si desidera visualizzare il contenuto quando una funzionalità o un set di funzionalità sono disabilitate. Se si specifica negate="true", come negli esempi seguenti, il rendering del contenuto viene eseguito solo quando FeatureX è disabilitato.
<feature negate="true" name="FeatureX">
<p>This content appears only when 'FeatureX' is disabled.</p>
</feature>
<feature negate="true" name="FeatureX" variant="Alpha">
<p>This content appears only when variant 'Alpha' of 'FeatureX' isn't assigned.</p>
</feature>
È possibile usare il <feature> tag per fare riferimento a più funzionalità. A tale scopo, specificare un elenco delimitato da virgole di funzionalità nell'attributo name .
<feature name="FeatureX,FeatureY">
<p>This content appears only when 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
Per impostazione predefinita, per il rendering del tag di funzionalità è necessario abilitare tutte le funzionalità elencate. È possibile eseguire l'override di questo comportamento aggiungendo l'attributo requirement , come illustrato nell'esempio seguente.
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This content appears only when 'FeatureX,' 'FeatureY,' or both are enabled.</p>
</feature>
È anche possibile usare il <feature> tag per fare riferimento a più varianti. A tale scopo, usare un requirement valore di Any e specificare un elenco delimitato da virgole di varianti nell'attributo variant .
<feature name="FeatureX" variant="Alpha,Beta" requirement="Any">
<p>This content appears only when variant 'Alpha' or 'Beta' of 'FeatureX' is assigned.</p>
</feature>
Note
- Se si specifica una variante, è necessario specificare una sola funzionalità.
- Se si specificano più varianti e si usa un
requirementvalore diAnd, viene generato un errore. Non è possibile assegnare più varianti.
Il tag <feature> richiede il funzionamento di un helper tag. Per usare il tag, aggiungere l'helper tag di gestione delle funzionalità al file _ViewImports.cshtml .
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore
Filtri MVC
È possibile configurare filtri di azione MVC applicati in modo condizionale in base allo stato di una funzionalità. Per configurare questi filtri, registrarli in modo compatibile con le funzionalità. La pipeline di gestione delle funzionalità supporta filtri di azione MVC asincroni che implementano l'interfaccia IAsyncActionFilter .
services.AddMvc(o =>
{
o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});
Il codice precedente registra un filtro MVC denominato SomeMvcFilter. Questo filtro viene attivato solo all'interno della pipeline MVC se FeatureX è abilitato.
Pagine Razor
Le pagine Razor MVC possono richiedere l'abilitazione di una determinata funzionalità o di un elenco di funzionalità per l'esecuzione. È possibile aggiungere questo requisito usando un FeatureGateAttribute oggetto . La classe FeatureGateAttribute è definita nello spazio dei nomi Microsoft.FeatureManagement.Mvc.
[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
Il codice precedente configura una pagina Razor che richiede che FeatureX sia abilitata. Se la funzionalità non è abilitata, la pagina genera un risultato HTTP 404 (NotFound).
Quando si usa un oggetto FeatureGateAttribute nelle pagine Razor, è necessario posizionare il tipo di gestore di pagina FeatureGateAttribute. Non è possibile inserirlo nei singoli metodi del gestore.
Compilazione dell'applicazione
È possibile usare la libreria di gestione delle funzionalità per aggiungere rami di applicazioni e middleware che vengono eseguiti in modo condizionale in base allo stato di una funzionalità.
app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");
Nel codice precedente, l'applicazione aggiunge un componente middleware visualizzato nella pipeline di richiesta solo se la FeatureX funzionalità è abilitata. Se la funzionalità è abilitata o disabilitata durante il runtime, la pipeline del middleware può essere modificata in modo dinamico.
Come illustrato nel codice seguente, questa funzionalità crea la funzionalità più generica per diramare l'intera applicazione in base a una funzionalità.
app.UseForFeature(featureName, appBuilder =>
{
appBuilder.UseMiddleware<T>();
});
Implementare un filtro di funzionalità
La creazione di un filtro di funzionalità consente di abilitare le funzionalità in base ai criteri definiti dall'utente. Per implementare un filtro di funzionalità, è necessario implementare l'interfaccia IFeatureFilter .
IFeatureFilter ha un solo metodo denominato EvaluateAsync. Quando una funzionalità specifica che può essere abilitata per un filtro di funzionalità, viene chiamato il metodo EvaluateAsync. Se EvaluateAsync restituisce true, la funzionalità deve essere abilitata.
Il codice seguente illustra come aggiungere un filtro di funzionalità personalizzato denominato MyCriteriaFilter.
services.AddFeatureManagement()
.AddFeatureFilter<MyCriteriaFilter>();
È possibile registrare un filtro di funzionalità chiamando AddFeatureFilter<T> sull'implementazione di IFeatureManagementBuilder che AddFeatureManagement restituisce. Il filtro delle funzionalità ha accesso ai servizi nella raccolta di servizi usata per aggiungere flag di funzionalità. È possibile usare l'inserimento delle dipendenze per recuperare questi servizi.
Note
Quando si fa riferimento ai filtri nelle impostazioni del flag di funzionalità (ad esempio, appsettings.json), è necessario omettere la parte Filter del nome del tipo. Per altre informazioni, vedere Filtrare l'attributo alias più avanti in questo articolo.
Filtri delle funzionalità con parametri
Alcuni filtri di funzionalità richiedono parametri per valutare se una funzionalità deve essere attivata. Ad esempio, un filtro di funzionalità del browser potrebbe attivare una funzionalità per un determinato set di browser. Potresti voler attivare una funzionalità nei browser Microsoft Edge e Chrome, ma non in Firefox.
Per implementare questo filtro, è possibile progettare un filtro di funzionalità per prevedere i parametri. Questi parametri vengono specificati nella configurazione della funzionalità. Nel codice è possibile accedervi tramite il FeatureFilterEvaluationContext parametro di IFeatureFilter.EvaluateAsync.
public class FeatureFilterEvaluationContext
{
/// <summary>
/// The name of the feature being evaluated
/// </summary>
public string FeatureName { get; set; }
/// <summary>
/// The settings provided for the feature filter to use when evaluating whether the feature should be enabled
/// </summary>
public IConfiguration Parameters { get; set; }
}
La FeatureFilterEvaluationContext classe ha una proprietà denominata Parameters. I parametri di questa proprietà rappresentano una configurazione non elaborata che il filtro delle funzionalità può usare quando si valuta se la funzionalità deve essere abilitata. Nell'esempio di filtro delle funzionalità del browser, il filtro può utilizzare la Parameters proprietà per estrarre un set di browser consentiti specificati per la funzionalità. Il filtro può quindi verificare se la richiesta proviene da uno di questi browser.
[FilterAlias("Browser")]
public class BrowserFilter : IFeatureFilter
{
…
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
BrowserFilterSettings settings = context.Parameters.Get<BrowserFilterSettings>() ?? new BrowserFilterSettings();
//
// Use the settings to check whether the request is from a browser in BrowserFilterSettings.AllowedBrowsers.
}
}
Attributo alias del filtro
Quando un filtro di funzionalità viene registrato per un flag di funzionalità, l'alias usato nella configurazione è il nome del tipo di filtro delle funzionalità con il suffisso Filter, se presente, rimosso. Ad esempio, è necessario fare riferimento a MyCriteriaFilter come MyCriteria nella configurazione.
{
"id": "MyFeature",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "MyCriteria"
}
]
}
}
È possibile eseguire l'override di questo nome usando la FilterAliasAttribute classe . Per dichiarare un nome da usare nella configurazione per fare riferimento a un filtro di funzionalità all'interno di un flag di funzionalità, è possibile decorare il filtro delle funzionalità con questo attributo.
Filtri delle funzionalità mancanti
Si supponga di configurare una funzionalità da abilitare per un filtro di funzionalità specifico. Se tale filtro di funzionalità non è registrato, viene generata un'eccezione quando viene valutata la funzionalità. Come illustrato nel codice seguente, è possibile disabilitare l'eccezione usando le opzioni di gestione delle funzionalità.
services.Configure<FeatureManagementOptions>(options =>
{
options.IgnoreMissingFeatureFilters = true;
});
Usare HttpContext
I filtri delle funzionalità possono valutare se una funzionalità deve essere abilitata in base alle proprietà di una richiesta HTTP. Questo controllo viene eseguito controllando il contesto HTTP. Come illustrato nel codice seguente, un filtro di funzionalità può ottenere un riferimento al contesto HTTP usando l'inserimento delle dipendenze per ottenere un'implementazione di IHttpContextAccessor.
public class BrowserFilter : IFeatureFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
public BrowserFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
}
Per renderla disponibile, è necessario aggiungere l'implementazione IHttpContextAccessor al contenitore di inserimento delle dipendenze all'avvio. È possibile usare il metodo seguente per registrare l'implementazione nei IServiceCollection servizi.
public void ConfigureServices(IServiceCollection services)
{
…
services.AddHttpContextAccessor();
…
}
Avanzato:IHttpContextAccessor e HttpContext non devono essere usati nei componenti Razor delle app Blazor lato server.
L'approccio consigliato per passare il contesto HTTP nelle app Blazor consiste nel copiare i dati in un servizio con ambito. Per le app Blazor, è consigliabile usare AddScopedFeatureManagement per registrare i servizi di gestione delle funzionalità. Per altre informazioni, vedere Servizi di gestione delle funzionalità con ambito, nella parte precedente di questo articolo.
Fornire un contesto per la valutazione delle funzionalità
Nelle applicazioni console, non esiste alcun contesto ambientale, come ad esempio HttpContext, che i filtri di funzionalità possono utilizzare per verificare se una funzionalità deve essere attiva. In questo caso, le applicazioni devono fornire un oggetto che rappresenta un contesto per il sistema di gestione delle funzionalità per l'uso da parte dei filtri delle funzionalità. È possibile usare IVariantFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext) per fornire questo contesto. Per valutare lo stato di una funzionalità, i filtri delle funzionalità possono usare l'oggetto appContext fornito al gestore funzionalità.
MyAppContext context = new MyAppContext
{
AccountId = current.Id
};
if (await featureManager.IsEnabledAsync(feature, context))
{
…
}
Filtri delle funzionalità contestuali
I filtri delle funzionalità contestuali implementano l'interfaccia IContextualFeatureFilter<TContext>. Quando IVariantFeatureManager.IsEnabledAsync<TContext> viene chiamato, questi filtri per funzioni speciali possono sfruttare il contesto che viene passato. Il TContext parametro di tipo in IContextualFeatureFilter<TContext> descrive il tipo di contesto che il filtro può gestire. Quando si sviluppa un filtro di funzionalità contestuale, è possibile stabilire i requisiti per l'uso del filtro specificando un tipo di contesto.
Poiché ogni tipo è un discendente della Object classe , è possibile chiamare un filtro che implementa IContextualFeatureFilter<object> per qualsiasi contesto fornito. Il codice seguente fornisce un esempio di filtro di funzionalità contestuale specifico. In questo codice, una funzionalità è abilitata se un account si trova in un elenco configurato di account abilitati.
public interface IAccountContext
{
string AccountId { get; set; }
}
[FilterAlias("AccountId")]
class AccountIdFilter : IContextualFeatureFilter<IAccountContext>
{
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureEvaluationContext, IAccountContext accountId)
{
//
// Evaluate whether the feature should be on by using the IAccountContext that's provided.
}
}
La AccountIdFilter classe richiede che venga fornito un oggetto che implementa IAccountContext per poter valutare lo stato di una funzionalità. Quando si usa questo filtro di funzionalità, il chiamante deve assicurarsi che l'oggetto passato implementi IAccountContext.
Note
È possibile implementare un'unica interfaccia di filtro funzionalità solo da un singolo tipo. Se si tenta di aggiungere un filtro di funzionalità che implementa più di un'unica interfaccia filtro funzionalità, viene generata un'eccezione ArgumentException .
Usare filtri contestuali e non contestuali con lo stesso alias
Filtri che implementano IFeatureFilter e IContextualFeatureFilter possono condividere lo stesso alias. In particolare, è possibile avere un alias di filtro condiviso da zero o una IFeatureFilter implementazione e zero o NIContextualFeatureFilter<ContextType> implementazioni se è presente al massimo un filtro applicabile per ContextType.
Per comprendere il processo di selezione di un filtro quando i filtri contestuali e non contestuali con lo stesso nome vengono registrati in un'applicazione, considerare l'esempio seguente.
Tre filtri condividono l'alias SharedFilterName :
- Filtro non contestuale denominato
FilterA - Filtro contestuale denominato
FilterBche accetta unTypeBcontesto - Filtro contestuale denominato
FilterCche accetta unTypeCcontesto
Un flag di funzionalità denominato MyFeature usa il SharedFilterName filtro delle funzionalità nella relativa configurazione.
Se vengono registrati tutti e tre i filtri:
- Quando si chiama
IsEnabledAsync("MyFeature"), il filtroFilterAviene usato per valutare il flag di funzionalità. - Quando chiami
IsEnabledAsync("MyFeature", context):- Se il tipo di
contextèTypeB,FilterBviene utilizzato . - Se il tipo di
contextèTypeC,FilterCviene utilizzato . - Se il tipo di
contextèTypeF,FilterAviene utilizzato .
- Se il tipo di
Filtri di funzionalità predefiniti
Esistono alcuni filtri di funzionalità disponibili con il Microsoft.FeatureManagement pacchetto : PercentageFilter, TimeWindowFilter, ContextualTargetingFiltere TargetingFilter. Tutti i filtri, ad eccezione di TargetingFilter, vengono aggiunti automaticamente usando il metodo per registrare la gestione delle AddFeatureManagement funzionalità.
TargetingFilter viene aggiunto utilizzando il WithTargeting metodo . Per altre informazioni, vedere Targeting, più avanti in questo articolo.
Ognuno dei filtri di funzionalità predefiniti ha i propri parametri. Le sezioni seguenti descrivono questi filtri di funzionalità e forniscono esempi.
Microsoft.Percentage
Il Microsoft.Percentage filtro consente di abilitare una funzionalità in base a una percentuale impostata.
{
"id": "EnhancedPipeline",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Microsoft.Percentage",
"parameters": {
"Value": 50
}
}
]
}
}
Microsoft.TimeWindow
Il Microsoft.TimeWindow filtro consente di abilitare una funzionalità in base a un intervallo di tempo.
- Se si specifica solo un
Endvalore, la funzionalità viene considerata attiva fino a quel momento. - Se si specifica solo un
Startvalore, la funzionalità viene considerata attiva in tutti i punti dopo quel momento.
{
"id": "EnhancedPipeline",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Sun, 01 Jun 2025 13:59:59 GMT",
"End": "Fri, 01 Aug 2025 00:00:00 GMT"
}
}
]
}
}
È possibile configurare il filtro per applicare un intervallo di tempo a intervalli ricorrenti. Questa funzionalità può essere utile quando è necessario attivare una funzionalità durante un periodo di traffico basso o elevato di un giorno o di alcuni giorni della settimana. Per espandere una singola finestra temporale a un intervallo di tempo ricorrente, usare un Recurrence parametro per specificare una regola di ricorrenza.
Note
Per usare la ricorrenza, è necessario specificare i valori Start e End. Con ricorrenza, la parte della data del valore End non specifica una data di fine per considerare attivo il filtro. Il filtro usa invece la data di fine, rispetto alla data di inizio, per definire la durata dell'intervallo di tempo che si ripete.
{
"id": "EnhancedPipeline",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Fri, 22 Mar 2024 20:00:00 GMT",
"End": "Sat, 23 Mar 2024 02:00:00 GMT",
"Recurrence": {
"Pattern": {
"Type": "Daily",
"Interval": 1
},
"Range": {
"Type": "NoEnd"
}
}
}
}
]
}
}
Le Recurrence impostazioni sono costituite da due parti:
- Le
Patternimpostazioni specificano la frequenza di ripetizione dell'intervallo di tempo. - Le
Rangeimpostazioni specificano la durata della ripetizione dello schema di ricorrenza.
Criterio di ricorrenza
Esistono due possibili tipi di criteri di ricorrenza: Daily e Weekly. Ad esempio, un intervallo di tempo può ripetersi ogni giorno, ogni tre giorni, ogni lunedì o ogni altro venerdì.
A seconda del tipo, alcuni campi delle Pattern impostazioni sono obbligatori, facoltativi o ignorati.
DailyIl criterio di ricorrenza giornaliera fa sì che l'intervallo di tempo si ripeta in base a un numero specificato di giorni tra ogni occorrenza.
Proprietà Pertinenza Descrizione TypeObbligatoria Tipo di modello di ricorrenza. Il valore deve essere impostato su Daily.IntervalFacoltativo Numero di giorni tra ogni occorrenza. Il valore predefinito è 1.WeeklyIl criterio di ricorrenza settimanale fa sì che l'intervallo di tempo si ripeta nello stesso giorno o giorni della settimana. È tuttavia possibile specificare il numero di settimane tra ogni set di occorrenze.
Proprietà Pertinenza Descrizione TypeObbligatoria Tipo di schema di ricorrenza. Il valore deve essere impostato su Weekly.DaysOfWeekObbligatoria I giorni della settimana in cui si verifica l'evento. IntervalFacoltativo Il numero di settimane tra ciascuna serie di occorrenze. Il valore predefinito è 1.FirstDayOfWeekFacoltativo Giorno da utilizzare come primo giorno della settimana. Il valore predefinito è Sunday.L'esempio seguente ripete l'intervallo di tempo ogni lunedì e martedì:
"Pattern": { "Type": "Weekly", "Interval": 2, "DaysOfWeek": ["Monday", "Tuesday"] }
Note
Il Start valore deve essere una prima occorrenza valida che si adatta al criterio di ricorrenza. Inoltre, la durata dell'intervallo di tempo non può essere più lunga della frequenza con cui si verifica. Ad esempio, un intervallo di tempo di 25 ore non può ripetersi ogni giorno.
Intervallo ricorrenza
Esistono tre possibili tipi di intervallo di ricorrenza: NoEnd, EndDatee Numbered.
NoEndL'intervallo
NoEndfa sì che la ricorrenza venga eseguita per un periodo illimitato.Proprietà Pertinenza Descrizione TypeObbligatoria Tipo di intervallo di ricorrenza. Il valore deve essere impostato su NoEnd.EndDateL'intervallo
EndDatefa sì che l'intervallo di tempo si verifichi in tutti i giorni che soddisfano il criterio applicabile fino alla data di fine.Proprietà Pertinenza Descrizione TypeObbligatoria Tipo di intervallo di ricorrenza. Il valore deve essere impostato su EndDate.EndDateObbligatoria Data e ora di interruzione dell'applicazione del modello. Se l'ora di inizio dell'ultima occorrenza è precedente alla data di fine, l'ora di fine di tale occorrenza può estendersi oltre. Nell'esempio seguente l'intervallo di tempo viene ripetuto ogni giorno fino all'ultima occorrenza del 1° aprile 2024.
"Start": "Fri, 22 Mar 2024 18:00:00 GMT", "End": "Fri, 22 Mar 2024 20:00:00 GMT", "Recurrence":{ "Pattern": { "Type": "Daily", "Interval": 1 }, "Range": { "Type": "EndDate", "EndDate": "Mon, 1 Apr 2024 20:00:00 GMT" } }NumberedL'intervallo
Numberedfa sì che l'intervallo di tempo si verifichi un numero specificato di volte.Proprietà Pertinenza Descrizione TypeObbligatoria Tipo di intervallo di ricorrenza. Il valore deve essere impostato su Numbered.NumberOfOccurrencesObbligatoria Numero di occorrenze. Nell'esempio seguente l'intervallo di tempo viene ripetuto lunedì e martedì per un totale di tre occorrenze, che si verificano nelle date seguenti:
- Lunedì, Aprile 1
- Martedì, Aprile 2
- Lunedì, Aprile 8
"Start": "Mon, 1 Apr 2024 18:00:00 GMT", "End": "Mon, 1 Apr 2024 20:00:00 GMT", "Recurrence":{ "Pattern": { "Type": "Weekly", "Interval": 1, "DaysOfWeek": ["Monday", "Tuesday"] }, "Range": { "Type": "Numbered", "NumberOfOccurrences": 3 } }
Per creare una regola di ricorrenza, è necessario specificare sia Pattern che Range le impostazioni. Qualsiasi tipo di criterio può funzionare con qualsiasi tipo di intervallo.
Avanzate: l'offset del fuso orario della proprietà Start viene applicato alle impostazioni di ricorrenza.
Microsoft.Targeting
Il Microsoft.Targeting filtro consente di abilitare una funzionalità per un gruppo di destinatari di destinazione. Per una spiegazione approfondita della targetizzazione, vedere Targeting, più avanti in questo articolo.
I parametri di filtro includono un Audience oggetto che descrive chi può accedere alla funzionalità. All'interno dell'oggetto Audience è possibile specificare utenti, gruppi, utenti e gruppi esclusi e una percentuale predefinita della base utenti.
Per ogni oggetto gruppo elencato nella Groups sezione, è necessario specificare anche la percentuale di accesso ai membri del gruppo.
Per ogni utente, la funzionalità viene valutata nel modo seguente:
Se l'utente viene escluso, la funzionalità viene disabilitata per l'utente. È possibile escludere l'utente da:
- Elencare il nome in
Usersnella sezioneExclusion. - Elencare un gruppo sotto
Groupscui appartengono, nella sezioneExclusion.
- Elencare il nome in
Se l'utente non è escluso, la funzionalità viene abilitata se vengono soddisfatte le condizioni seguenti:
- L'utente è elencato nella
Userssezione . - L'utente è nella percentuale inclusa di una delle implementazioni del gruppo.
- L'utente rientra nella percentuale di implementazione predefinita.
- L'utente è elencato nella
Se nessuno dei casi precedenti si applica, la funzionalità viene disabilitata per l'utente. Ad esempio, se l'utente non è incluso in una percentuale inclusa, la funzionalità è disabilitata.
{
"id": "EnhancedPipeline",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Microsoft.Targeting",
"parameters": {
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
},
{
"Name": "Ring1",
"RolloutPercentage": 50
}
],
"DefaultRolloutPercentage": 20,
"Exclusion": {
"Users": [
"Ross"
],
"Groups": [
"Ring2"
]
}
}
}
}
]
}
}
Spazi dei nomi alias del filtro di funzionalità
Tutti gli alias dei filtri di funzionalità predefiniti si trovano nello spazio dei nomi del Microsoft filtro di funzionalità. Essere in questo namespace previene conflitti con altri filtri di funzionalità che condividono lo stesso alias. I segmenti di uno spazio dei nomi del filtro di funzionalità sono divisi dal carattere .. È possibile fare riferimento a un filtro di funzionalità in base al relativo alias completo, ad esempio Microsoft.Percentage. In alternativa, è possibile fare riferimento all'ultimo segmento, ad esempio Percentage.
Destinazione
Il targeting è una strategia di gestione delle funzionalità che è possibile usare per distribuire progressivamente nuove funzionalità alla base utenti. La strategia si basa sul concetto di destinazione di un set di utenti noto come gruppo di destinatari. Un gruppo di destinatari è costituito da utenti, gruppi specifici, utenti e gruppi esclusi e una percentuale designata dell'intera base utente. I gruppi inclusi nel gruppo di destinatari possono essere suddivisi ulteriormente in percentuali dei membri totali.
I passaggi seguenti illustrano un esempio di implementazione progressiva per una nuova funzionalità denominata Beta:
- Ai singoli utenti Jeff e Alicia viene concesso l'accesso alla funzionalità Beta.
- Un altro utente, Mark, chiede di acconsentire esplicitamente ed è incluso.
- Il venti percento degli utenti nel gruppo Ring1 è incluso nella funzionalità Beta.
- Il numero di utenti di Ring1 inclusi è stato incrementato fino al 100%.
- Il 5% della base utente è incluso nella funzionalità Beta.
- La percentuale di implementazione viene incrementata fino al 100% per implementare completamente la funzionalità.
La libreria supporta questa strategia per l'implementazione di una funzionalità tramite il filtro di funzionalità Microsoft.Targeting predefinito.
Targetizzazione in un'applicazione web
Per un esempio di applicazione Web che usa il filtro di funzionalità di destinazione, vedere il progetto di esempio FeatureFlagDemo .
Per iniziare a usare TargetingFilter in un'applicazione, è necessario aggiungerlo alla raccolta di servizi dell'applicazione esattamente come qualsiasi altro filtro di funzionalità. A differenza di altri filtri predefiniti, TargetingFilter si basa su un altro servizio da aggiungere alla raccolta di servizi dell'applicazione. Tale servizio è un'implementazione ITargetingContextAccessor .
La Microsoft.FeatureManagement.AspNetCore libreria fornisce un'implementazione predefinita di ITargetingContextAccessor che estrae le informazioni di destinazione dal valore di HttpContext una richiesta. È possibile usare la funzione di accesso del contesto di destinazione predefinita quando si configura la destinazione usando l'overload non generico WithTargeting in IFeatureManagementBuilder.
Per registrare la funzione di accesso al contesto di destinazione predefinita e TargetingFilter, chiamare WithTargeting su IFeatureManagementBuilder.
services.AddFeatureManagement()
.WithTargeting();
È anche possibile registrare un'implementazione personalizzata per ITargetingContextAccessor e TargetingFilter chiamando WithTargeting<T>. Il codice seguente configura la gestione delle funzionalità in un'applicazione Web da usare TargetingFilter con un'implementazione di ITargetingContextAccessor denominata ExampleTargetingContextAccessor.
services.AddFeatureManagement()
.WithTargeting<ExampleTargetingContextAccessor>();
ITargetingContextAccessor
Per usare TargetingFilter in un'applicazione Web, è necessaria un'implementazione di ITargetingContextAccessor . Il motivo alla base di questo requisito è che per le valutazioni di destinazione sono necessarie informazioni contestuali, ad esempio informazioni sull'utente. Queste informazioni vengono archiviate in istanze della TargetingContext classe . Applicazioni diverse estraggono queste informazioni da posizioni diverse, ad esempio il contesto HTTP di una richiesta o un database.
Per un esempio che estrae informazioni sul contesto di destinazione dal contesto HTTP di un'applicazione, vedere DefaultHttpTargetingContextAccessor nel Microsoft.FeatureManagement.AspNetCore pacchetto. Estrae le informazioni seguenti:
- Mirare alle informazioni dalla proprietà
HttpContext.User -
UserIdinformazioni dalIdentity.Namecampo -
Groupsinformazioni provenienti da attestazioni di tipoRole
Questa implementazione si basa sull'uso di IHttpContextAccessor. Per altre informazioni su IHttpContextAccessor, vedere Usare HttpContext, in precedenza in questo articolo.
Destinazione in un'applicazione console
Il filtro di destinazione si basa su un contesto di destinazione per valutare se una funzionalità deve essere attivata. Questo contesto di destinazione contiene informazioni quali l'utente che viene valutato e i gruppi a cui appartiene l'utente. Nelle applicazioni console, in genere non è disponibile alcun contesto ambientale per passare queste informazioni al filtro di destinazione. Di conseguenza, devi passarlo direttamente quando chiami FeatureManager.IsEnabledAsync. Questo tipo di contesto è supportato tramite ContextualTargetingFilter. Le applicazioni che devono inviare il contesto di destinazione al gestore delle funzionalità devono usare ContextualTargetingFilter invece di TargetingFilter.
Poiché ContextualTargetingFilter implementa IContextualTargetingFilter<ITargetingContext>, è necessario passare un'implementazione di ITargetingContext a IVariantFeatureManager.IsEnabledAsync per poter valutare e attivare una funzionalità.
IVariantFeatureManager fm;
…
// The userId and groups variables are defined earlier in the application.
TargetingContext targetingContext = new TargetingContext
{
UserId = userId,
Groups = groups
};
await fm.IsEnabledAsync(featureName, targetingContext);
ContextualTargetingFilter usa l'alias Microsoft.Targetingdel filtro delle funzionalità , quindi la configurazione per questo filtro è coerente con le informazioni contenute in Microsoft.Targeting, in precedenza in questo articolo.
Per un esempio che usa ContextualTargetingFilter in un'applicazione console, vedere il progetto di esempio TargetingConsoleApp .
Opzioni di valutazione di destinazione
Le opzioni sono disponibili per personalizzare la modalità di esecuzione della valutazione della destinazione in tutte le funzionalità. È possibile configurare queste opzioni quando si configura la gestione delle funzionalità.
services.Configure<TargetingEvaluationOptions>(options =>
{
options.IgnoreCase = true;
});
Esclusione di targeting
Quando si definisce un gruppo di destinatari, è possibile escludere utenti e gruppi dal gruppo di destinatari. Questa funzionalità è utile quando si esegue l'implementazione di una funzionalità a un gruppo di utenti, ma è necessario escludere alcuni utenti o gruppi dall'implementazione. Per specificare utenti e gruppi da escludere, usare la Exclusion proprietà di un gruppo di destinatari.
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0,
"Exclusion": {
"Users": [
"Mark"
]
}
}
Il codice precedente abilita una funzionalità per gli utenti denominati Jeff e Alicia. La funzionalità è abilitata anche per gli utenti del gruppo denominato Ring0. Tuttavia, la funzionalità è disabilitata per l'utente denominato Mark, anche se tale utente si trova nel Ring0 gruppo. Le esclusioni hanno la priorità rispetto al resto del filtro di destinazione.
Varianti
In alcuni casi, quando si aggiunge una nuova funzionalità a un'applicazione, la funzionalità include più opzioni di progettazione proposte. I test A/B offrono una soluzione comune per decidere una progettazione. Il test A/B prevede la fornitura di una versione diversa della funzionalità a segmenti diversi della base utente e quindi la scelta di una versione in base all'interazione dell'utente. Nella libreria di gestione delle funzionalità .NET è possibile implementare test A/B usando varianti per rappresentare varie configurazioni di una funzionalità.
Le varianti consentono a un flag di funzionalità di diventare più di un flag on/off di base. Una variante rappresenta un valore di un flag di funzionalità che può essere una stringa, un numero, un valore booleano o anche un oggetto di configurazione. Un flag di funzionalità che dichiara varianti deve definire le circostanze in cui deve essere usata ogni variante. Per altre informazioni, vedere Allocare varianti più avanti in questo articolo.
public class Variant
{
/// <summary>
/// The name of the variant
/// </summary>
public string Name { get; set; }
/// <summary>
/// The configuration of the variant
/// </summary>
public IConfigurationSection Configuration { get; set; }
}
Recuperare varianti
Per ogni funzionalità, è possibile recuperare una variante usando il GetVariantAsync metodo dell'interfaccia IVariantFeatureManager .
…
IVariantFeatureManager featureManager;
…
Variant variant = await featureManager.GetVariantAsync("MyVariantFeatureFlag", CancellationToken.None);
IConfigurationSection variantConfiguration = variant.Configuration;
// Do something with the resulting variant and its configuration.
Dopo aver recuperato una variante, è possibile utilizzare la sua configurazione direttamente come implementazione di IConfigurationSection, derivata dalla proprietà Configuration della variante. Un'altra opzione consiste nell'associare la configurazione a un oggetto usando il modello di associazione di configurazione .NET.
IConfigurationSection variantConfiguration = variant.Configuration;
MyFeatureSettings settings = new MyFeatureSettings();
variantConfiguration.Bind(settings);
La variante restituita dipende dall'utente che viene valutato. È possibile ottenere informazioni sull'utente da un'istanza di TargetingContext. È possibile passare il contesto quando si richiama GetVariantAsync. In alternativa, può essere recuperato automaticamente da un'implementazione di ITargetingContextAccessor se ne viene registrata una.
Dichiarazione delle varianti dell'indicatore di funzionalità
Rispetto ai flag di funzionalità standard, i flag di funzionalità varianti hanno due proprietà aggiuntive: variants e allocation. La variants proprietà è una matrice che contiene le varianti definite per la funzionalità. La proprietà allocation definisce la modalità di allocazione di queste varianti per la funzionalità. Proprio come dichiarare flag di funzionalità standard, è possibile configurare flag di funzionalità varianti in un file JSON. Il codice seguente è un esempio di un flag di funzionalità variabile.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"default_when_enabled": "Small",
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
]
},
"variants": [
{
"name": "Big"
},
{
"name": "Small"
}
]
}
]
}
}
Definire varianti
Ogni variante ha due proprietà: un nome e una configurazione. Il nome viene usato per fare riferimento a una variante specifica e la configurazione è il valore di tale variante. È possibile utilizzare la configuration_value proprietà per specificare la configurazione. La configuration_value proprietà è una configurazione inline che può essere una stringa, un numero, un valore booleano o un oggetto di configurazione. Se non si configura la configuration_value proprietà , la proprietà della Configuration variante restituita è null.
Per specificare tutte le possibili varianti per una funzionalità, elencarle sotto la variants proprietà .
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"variants": [
{
"name": "Big",
"configuration_value": {
"Size": 500
}
},
{
"name": "Small",
"configuration_value": {
"Size": 300
}
}
]
}
]
}
}
Allocare varianti
Per allocare le varianti di una funzionalità, usare la allocation proprietà della funzionalità.
"allocation": {
"default_when_enabled": "Small",
"default_when_disabled": "Small",
"user": [
{
"variant": "Big",
"users": [
"Marsha"
]
}
],
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
],
"percentile": [
{
"variant": "Big",
"from": 0,
"to": 10
}
],
"seed": "13973240"
},
"variants": [
{
"name": "Big",
"configuration_value": "500px"
},
{
"name": "Small",
"configuration_value": "300px"
}
]
L'impostazione allocation ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
default_when_disabled |
Variante da usare quando viene richiesta una variante mentre la funzionalità viene considerata disabilitata. |
default_when_enabled |
Variante da usare quando viene richiesta una variante mentre la funzionalità viene considerata abilitata e nessun'altra variante viene assegnata all'utente. |
user |
Una variante e un elenco di utenti a cui assegnare la variante. |
group |
Variante e elenco di gruppi. La variante viene assegnata se l'utente corrente si trova in almeno uno dei gruppi. |
percentile |
Una variante e un intervallo di percentuale entro il quale la percentuale calcolata dell'utente deve rientrare affinché possa essere assegnata la variante. |
seed |
Valore su cui si basano i calcoli percentuali per percentile . Il calcolo percentuale per un utente specifico è lo stesso in tutte le funzionalità se viene usato lo stesso seed valore. Se non viene specificato alcun valore seed, viene creato un valore di inizializzazione predefinito in base al nome della funzionalità. |
Se una funzionalità non è abilitata, gestione funzionalità assegna la variante specificata per default_when_disabled all'utente corrente. Nell'esempio precedente questa funzionalità è denominata Small.
Se la funzionalità è abilitata, il manager delle funzionalità verifica le allocazioni user, group e percentile in tale ordine al fine di assegnare una variante. Nell'esempio precedente, la variante specificata, Big, viene assegnata all'utente nei casi seguenti:
- L'utente valutato è denominato
Marsha. - L'utente si trova nel
Ring1gruppo. - L'utente ricade tra lo zeroth e il decimo percentile.
Se nessuna di queste allocazioni corrisponde, la default_when_enabled variante viene assegnata all'utente. Nell'esempio la variante è Small.
La logica di allocazione è simile alla logica usata per il filtro delle funzionalità Microsoft.Targeting . Esistono tuttavia alcuni parametri presenti nella destinazione che non sono nell'allocazione e viceversa. I risultati della destinazione e dell'allocazione non sono correlati.
Note
Per allocare varianti di funzionalità, è necessario registrare ITargetingContextAccessor chiamando il metodo WithTargeting<T>.
Eseguire l'override dello stato abilitato usando una variante
È possibile usare varianti per eseguire l'override dello stato abilitato di un flag di funzionalità. Quando si sfrutta questa funzionalità, è possibile estendere la valutazione di un flag di funzionalità. Durante la chiamata a IsEnabledAsync su un flag con varianti, il gestore delle funzionalità controlla se la variante assegnata all'utente corrente è configurata per eseguire l'override del risultato.
È possibile implementare l'override usando la proprietà facoltativa variante status_override. Questa proprietà può avere i valori seguenti:
-
None: la variante non influisce sul fatto che il flag sia considerato abilitato o disabilitato.Noneè il valore predefinito. -
Enabled: quando si seleziona la variante, il flag di funzionalità viene valutato come abilitato. -
Disabled: quando si seleziona la variante, il flag di funzionalità viene valutato come disabilitato.
Non è possibile sovrascrivere una funzionalità con uno stato enabled di false.
Se si usa un flag di funzionalità con varianti binarie, la status_override proprietà può essere utile. È possibile continuare a usare API come IsEnabledAsync e FeatureGateAttribute nell'applicazione. Ma è anche possibile trarre vantaggio dalle funzionalità fornite con varianti, ad esempio l'allocazione percentile e l'uso di un valore di inizializzazione per i calcoli percentuali.
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"percentile": [
{
"variant": "On",
"from": 10,
"to": 20
}
],
"default_when_enabled": "Off",
"seed": "Enhanced-Feature-Group"
},
"variants": [
{
"name": "On"
},
{
"name": "Off",
"status_override": "Disabled"
}
]
}
Nell'esempio precedente la funzionalità è sempre abilitata. Se l'utente corrente si trova nell'intervallo percentile calcolato compreso tra 10 e 20, viene restituita la On variante. In caso contrario, viene restituita la Off variante e, poiché il status_override valore è Disabled, la funzionalità viene considerata disabilitata.
Varianti nell'inserimento delle dipendenze
È possibile usare flag di funzionalità varianti insieme all'inserimento delle dipendenze per esporre implementazioni diverse di un servizio a utenti diversi. L'interfaccia IVariantServiceProvider<TService> consente di eseguire questa combinazione.
IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...
IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken);
Nel codice precedente, l'implementazione di IVariantServiceProvider<IAlgorithm> recupera un'implementazione di IAlgorithm dal contenitore per l'iniezione delle dipendenze. L'implementazione scelta dipende da:
- Flag di funzionalità con cui è registrato il
IAlgorithmservizio. - Variante allocata per tale funzionalità.
L'implementazione IVariantServiceProvider<T> viene resa disponibile per l'applicazione chiamando IFeatureManagementBuilder.WithVariantService<T>(string featureName), come illustrato nell'esempio seguente. La chiamata in questo codice rende IVariantServiceProvider<IAlgorithm> disponibile nella raccolta di servizi.
services.AddFeatureManagement()
.WithVariantService<IAlgorithm>("ForecastAlgorithm");
È necessario aggiungere ogni implementazione di IAlgorithm separatamente tramite un metodo add, services.AddSingleton<IAlgorithm, SomeImplementation>()ad esempio . L'implementazione di IAlgorithm che IVariantServiceProvider utilizza dipende dal flag di variante della funzionalità ForecastAlgorithm. Se non viene aggiunta alcuna implementazione di IAlgorithm alla raccolta di servizi, IVariantServiceProvider<IAlgorithm>.GetServiceAsync() restituisce un'attività con un risultato null.
{
// The example variant feature flag
"id": "ForecastAlgorithm",
"enabled": true,
"variants": [
{
"Name": "AlgorithmBeta"
},
...
]
}
Attributo alias del servizio delle varianti
Il provider di servizi variant usa i nomi dei tipi di implementazioni per trovare la corrispondenza con la variante allocata. Se un servizio variant è decorato con VariantServiceAliasAttribute, il nome dichiarato in questo attributo deve essere usato nella configurazione per fare riferimento a questo servizio variante.
[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
...
}
Telemetria
Quando si distribuisce una modifica del flag di funzionalità, spesso è importante analizzarne l'effetto su un'applicazione. Ecco alcune domande che possono verificarsi, ad esempio:
- Le bandiere sono attivate e disattivate come previsto?
- Gli utenti di destinazione ottengono l'accesso a una determinata funzionalità come previsto?
- Quale variante viene visualizzata da un utente specifico?
L'emissione e l'analisi degli eventi di valutazione dei flag di funzionalità possono aiutarti a rispondere a questioni di questo tipo. La libreria .NET per la gestione delle funzionalità utilizza l'API System.Diagnostics.Activity per generare telemetria di tracciamento durante la valutazione dei flag di funzionalità.
Abilitare i dati di telemetria
Per impostazione predefinita, i flag di funzionalità non hanno dati di telemetria generati. Per pubblicare i dati di telemetria per un determinato flag di funzionalità, il flag deve dichiarare che è abilitato per l'emissione di dati di telemetria.
Per i flag di funzionalità definiti in appsettings.json, è possibile abilitare la telemetria usando telemetry proprietà.
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
Il codice precedente da un file appsettings.json definisce un feature flag denominato MyFeatureFlag abilitato per la telemetria. Lo stato di telemetria è indicato dall'oggetto telemetry che imposta enabled su true. Il valore della proprietà enabled deve essere true per pubblicare i dati di telemetria per il flag.
La sezione telemetry di un flag di funzionalità ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
enabled |
Valore booleano che specifica se i dati di telemetria devono essere pubblicati per il flag di funzionalità. |
metadata |
Raccolta di coppie chiave-valore, modellate come dizionario, che è possibile usare per allegare metadati personalizzati relativi al flag di funzionalità agli eventi di valutazione. |
Pubblicazione di telemetria personalizzata
Il gestore delle funzionalità ha una propria istanza ActivitySource denominata Microsoft.FeatureManagement. Se la telemetria è abilitata per un flag di funzionalità:
- All'inizio di una valutazione del flag di funzionalità, il gestore delle funzionalità avvia un'istanza di
Activity. - Al termine della valutazione di un flag di funzionalità, il gestore delle funzionalità aggiunge un'istanza
ActivityEventdenominataFeatureFlagall'attività corrente.
L'evento FeatureFlag include tag che includono le informazioni sulla valutazione del flag di funzionalità. I tag usano i campi definiti nello schema FeatureEvaluationEvent .
Note
Tutte le coppie chiave-valore specificate nella telemetry.metadata proprietà del flag di funzionalità sono incluse anche nei tag.
Per abilitare la pubblicazione di dati di telemetria personalizzati, è possibile creare un'istanza di ActivityListener e ascoltare l'origine dell'attività Microsoft.FeatureManagement. Il codice seguente illustra come ascoltare l'origine dell'attività di gestione delle funzionalità e aggiungere un callback quando viene valutata una funzionalità.
ActivitySource.AddActivityListener(new ActivityListener()
{
ShouldListenTo = (activitySource) => activitySource.Name == "Microsoft.FeatureManagement",
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
ActivityStopped = (activity) =>
{
ActivityEvent? evaluationEvent = activity.Events.FirstOrDefault((activityEvent) => activityEvent.Name == "FeatureFlag");
if (evaluationEvent.HasValue && evaluationEvent.Value.Tags.Any())
{
// Do something.
}
}
});
Per altre informazioni, vedere Raccogliere una traccia distribuita.
Application Insights Telemetry
Il pacchetto Microsoft.FeatureManagement.Telemetry.ApplicationInsights fornisce un server di pubblicazione di telemetria predefinito che invia i dati di valutazione dei flag di funzionalità ad Application Insights. Il Microsoft.FeatureManagement.Telemetry.ApplicationInsights pacchetto fornisce anche un inizializzatore di telemetria che contrassegna automaticamente tutti gli eventi con TargetingId in modo che gli eventi possano essere collegati alle valutazioni dei flag. Per sfruttare questa funzionalità, aggiungere un riferimento al pacchetto e registrare i dati di telemetria di Application Insights. Nel codice seguente ne viene illustrato un esempio:
builder.services
.AddFeatureManagement()
.AddApplicationInsightsTelemetry();
Note
Per garantire che i dati di telemetria di Application Insights funzionino come previsto, è consigliabile usare la TargetingHttpContextMiddleware classe .
Per abilitare la persistenza del contesto di destinazione nell'attività corrente, è possibile usare la TargetingHttpContextMiddleware classe .
app.UseMiddleware<TargetingHttpContextMiddleware>();
Per un esempio dell'utilizzo, vedere l'esempio VariantAndTelemetryDemo .
Prerequisito
Il pubblicatore di telemetria fornito dal Microsoft.FeatureManagement.Telemetry.ApplicationInsights pacchetto richiede che Application Insights sia configurato e registrato come servizio applicativo. Per il codice di esempio, vedere l'applicazione di esempio VariantAndTelemetryDemo .
Memorizzazione nella cache
Lo stato della funzionalità viene fornito dal sistema IConfiguration. È previsto che i provider di configurazione gestiscano qualsiasi memorizzazione nella cache e aggiornamento dinamico. Il gestore delle funzionalità chiede IConfiguration il valore più recente dello stato di una funzionalità ogni volta che valuta se una funzionalità è abilitata.
Snapshot
Alcuni scenari richiedono che lo stato di una funzionalità rimanga coerente durante la durata di una richiesta. I valori restituiti da un'implementazione standard IVariantFeatureManager possono cambiare se l'origine IConfiguration da cui esegue il pull viene aggiornata durante la richiesta.
È possibile impedire questo comportamento usando IVariantFeatureManagerSnapshot. È possibile recuperare IVariantFeatureManagerSnapshot nello stesso modo di IVariantFeatureManager.
IVariantFeatureManagerSnapshot implementa l'interfaccia IVariantFeatureManager , ma IVariantFeatureManagerSnapshot memorizza nella cache il primo stato valutato di una funzionalità durante una richiesta. Restituisce lo stato durante la durata della funzionalità.
Provider di funzionalità personalizzati
Quando si implementa un provider di funzionalità personalizzato, è possibile recuperare i flag di funzionalità dall'origine, ad esempio un database o un servizio di gestione delle funzionalità. Il provider di funzionalità predefinito recupera i flag di funzionalità dal sistema di configurazione di .NET Core. Questo sistema fornisce supporto per la definizione delle funzionalità in un file appsettings.json o nei provider di configurazione come Configurazione app di Azure. È possibile personalizzare questo comportamento per controllare la posizione di lettura delle definizioni delle funzionalità.
Per personalizzare il caricamento delle definizioni di funzionalità, è necessario implementare l'interfaccia IFeatureDefinitionProvider .
public interface IFeatureDefinitionProvider
{
Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);
IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}
Per usare un'implementazione di IFeatureDefinitionProvider, è necessario aggiungerla alla raccolta di servizi prima di aggiungere la gestione delle funzionalità. Nell'esempio di codice seguente viene aggiunta un'implementazione di IFeatureDefinitionProvider denominata InMemoryFeatureDefinitionProvider.
services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
.AddFeatureManagement()
Passaggi successivi
Per informazioni su come usare i flag di funzionalità nelle applicazioni, vedere le guide introduttive seguenti:
Per informazioni su come usare i filtri delle funzionalità, vedere le esercitazioni seguenti: