.NET-funktionshantering

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore
Microsoft.FeatureManagement.Telemetry.ApplicationInsights

Med .NET-funktionshanteringsbiblioteket kan du utveckla och exponera programfunktioner baserat på funktionsflaggor. När en ny funktion har utvecklats har många program särskilda krav, till exempel när funktionen ska aktiveras och under vilka villkor. Det här biblioteket är ett sätt att definiera dessa relationer och integreras även i vanliga .NET-kodmönster för att göra det möjligt att exponera dessa funktioner.

Funktionsflaggor är ett sätt för .NET- och ASP.NET Core-program att aktivera eller inaktivera funktioner dynamiskt. Utvecklare kan använda funktionsflaggor i enkla användningsfall som villkorssatser till mer avancerade scenarier som att villkorligt lägga till vägar eller MVC-filter. Funktionsflaggor bygger på .NET Core-konfigurationssystemet. Alla .NET Core-konfigurationsprovider kan fungera som stamnät för funktionsflaggor.

Här är några av fördelarna med att använda .NET-funktionshanteringsbiblioteket:

  • En vanlig konvention för funktionshantering

  • Låg barriär mot ingång

    • Byggd på IConfiguration
    • Stöder konfiguration av JSON-filfunktionsflagga
  • Livslängdshantering för funktionsflagga

    • Konfigurationsvärden kan ändras i realtid. funktionsflaggor kan vara konsekventa i hela begäran
  • Enkla till komplexa scenarier som omfattas

    • Växla på/av-funktioner via deklarativ konfigurationsfil
    • Utvärdera funktionstillstånd dynamiskt baserat på anrop till server
  • API-tillägg för ASP.NET Core- och MVC-ramverk

    • Routning
    • Filter
    • Åtgärdsattribut

    .NET-funktionshanteringsbiblioteket är öppen källkod. Mer information finns på GitHub-lagringsplatsen.

Funktionsflaggor

Funktionsflaggor består av två delar, ett namn och en lista över funktionsfilter som används för att aktivera funktionen.

Funktionsfilter

Funktionsfilter definierar ett scenario för när en funktion ska aktiveras. När en funktion utvärderas för om den är på eller av bläddras listan över funktionsfilter igenom tills ett av filtren bestämmer att funktionen ska aktiveras. I det här läget anses funktionen vara aktiverad och genomströmning via funktionsfiltren stoppas. Om inget funktionsfilter anger att funktionen ska vara aktiverad anses den vara inaktiverad.

Ett funktionsfilter för Microsoft Edge-webbläsare kan till exempel utformas. Det här funktionsfiltret aktiverar alla funktioner som det är kopplat till så länge en HTTP-begäran kommer från Microsoft Edge.

Konfiguration av funktionsflagga

.NET Core-konfigurationssystemet används för att fastställa tillståndet för funktionsflaggor. Grunden för det här systemet är IConfiguration. Valfri provider för IConfiguration kan användas som funktionstillståndsprovider för funktionsflaggabiblioteket. Det här systemet möjliggör scenarier som sträcker sig från appsettings.json till Azure App Configuration med mera.

Deklaration av funktionsflagga

Funktionshanteringsbiblioteket stöder appsettings.json som en funktionsflaggakälla eftersom det är en provider för .NET Cores IConfiguration system. Nedan visas ett exempel på det format som används för att konfigurera funktionsflaggor i en json-fil.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in a json file
    "FeatureManagement": {
        "FeatureT": {
            "EnabledFor": [
                {
                    "Name": "AlwaysOn"
                }
            ]
        },
        "FeatureU": {
            "EnabledFor": []
        },
        "FeatureV": {
            "EnabledFor": [
                {
                    "Name": "TimeWindow",
                    "Parameters": {
                        "Start": "Wed, 01 May 2019 13:59:59 GMT",
                        "End": "Mon, 01 Jul 2019 00:00:00 GMT"
                    }
                }
            ]
        }
    }
}

Avsnittet FeatureManagement i json-dokumentet används av konventionen för att läsa in inställningar för funktionsflagga. I avsnittet ovan ser vi tre olika funktioner. Funktioner definierar sina funktionsfilter med hjälp av EnabledFor egenskapen . I funktionsfiltren för FeatureTser AlwaysOnvi . Det här funktionsfiltret är inbyggt och om det anges aktiveras alltid funktionen. Funktionsfiltret AlwaysOn kräver ingen konfiguration, så det har Name bara egenskapen . FeatureU har inga filter i egenskapen EnabledFor och kommer därför aldrig att aktiveras. Alla funktioner som förlitar sig på att den här funktionen är aktiverad kommer inte att vara tillgängliga så länge funktionsfiltren förblir tomma. Men så snart ett funktionsfilter har lagts till som aktiverar funktionen kan den börja fungera. FeatureV anger ett funktionsfilter med namnet TimeWindow. Det här är ett exempel på ett konfigurerbart funktionsfilter. Vi kan se i exemplet att filtret har en Parameters egenskap. Detta används för att konfigurera filtret. I det här fallet konfigureras start- och sluttiderna för funktionen som ska vara aktiv.

Det detaljerade schemat för FeatureManagement avsnittet finns här.

Avancerat: Användning av kolon :är förbjuden i funktionsflaggans namn.

Av/på-deklaration

Följande kodfragment visar ett alternativt sätt att definiera en funktion som kan användas för av/på-funktioner.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in config file
    "FeatureManagement": {
        "FeatureT": true, // On feature
        "FeatureX": false // Off feature
    }
}

RequirementType

Egenskapen RequirementType för en funktionsflagga används för att avgöra om filtren ska använda Any eller All logik när du utvärderar tillståndet för en funktion. Om RequirementType inte anges är Anystandardvärdet .

  • Any innebär att endast ett filter behöver utvärderas till sant för att funktionen ska aktiveras.
  • All innebär att varje filter måste utvärderas till sant för att funktionen ska aktiveras.

En RequirementType av All ändrar bläddringarna. Om det inte finns några filter inaktiveras funktionen. Sedan bläddras funktionsfiltren igenom tills ett av filtren bestämmer att funktionen ska inaktiveras. Om inget filter anger att funktionen ska inaktiveras anses den vara aktiverad.

"FeatureW": {
    "RequirementType": "All",
    "EnabledFor": [
        {
            "Name": "TimeWindow",
            "Parameters": {
                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                "End": "Sat, 01 Jul 2023 00:00:00 GMT"
            }
        },
        {
            "Name": "Percentage",
            "Parameters": {
                "Value": "50"
            }
        }
    ]
}

I exemplet ovan FeatureW anger en RequirementType av All, vilket innebär att alla dess filter måste utvärderas till true för att funktionen ska aktiveras. I det här fallet är funktionen aktiverad för 50 % av användarna under den angivna tidsperioden.

Microsofts funktionshanteringsschema

Funktionshanteringsbiblioteket stöder också användningen av för att deklarera funktionsflaggor Microsoft Feature Management schema . Det här schemat är språkberoende och stöds av alla Microsofts funktionshanteringsbibliotek.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": true,
                "conditions": {
                    "client_filters": [
                        {  
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                                "End": "Sat, 01 Jul 2023 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Kommentar

Om avsnittet feature_management finns i konfigurationen ignoreras avsnittet FeatureManagement .

Funktionshanteringsbiblioteket stöder appsettings.json som en funktionsflaggakälla eftersom det är en provider för .NET Cores IConfiguration system. Funktionsflaggor deklareras med hjälp av Microsoft Feature Management schema. Det här schemat är språkberoende och stöds av alla Microsofts funktionshanteringsbibliotek.

Nedan visas ett exempel på hur du deklarerar funktionsflaggor i en json-fil.

{
    "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": "Mon, 01 May 2023 13:59:59 GMT",
                                "End": "Sat, 01 July 2023 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Avsnittet feature_management i json-dokumentet används av konventionen för att läsa in inställningar för funktionsflagga. Funktionsflaggaobjekt måste anges i matrisen feature_flags under avsnittet feature_management . I avsnittet ovan ser vi att vi har tillhandahållit tre olika funktioner. En funktionsflagga har id och enabled egenskaper. id är det namn som används för att identifiera och referera till funktionsflaggan. Egenskapen enabled anger det aktiverade tillståndet för funktionsflaggan. En funktion är AV om enabled den är falsk. Om enabled är sant beror funktionens tillstånd på conditions. Om det inte finns några conditions så är funktionen PÅ. Om det finns conditions och de uppfylls är funktionen PÅ. Om det finns conditions och de inte uppfylls är funktionen AV. Egenskapen conditions deklarerar de villkor som används för att dynamiskt aktivera funktionen. Funktioner definierar sina funktionsfilter i matrisen client_filters . FeatureV anger ett funktionsfilter med namnet Microsoft.TimeWindow. Det här är ett exempel på ett konfigurerbart funktionsfilter. Vi kan se i exemplet att filtret har en Parameters egenskap. Detta används för att konfigurera filtret. I det här fallet konfigureras start- och sluttiderna för funktionen som ska vara aktiv.

Avancerat: Användning av kolon :är förbjuden i funktionsflaggans namn.

RequirementType

Egenskapen requirement_type conditions för används för att avgöra om filtren ska använda Any eller All logik när du utvärderar tillståndet för en funktion. Om requirement_type inte anges är Anystandardvärdet .

  • Any innebär att endast ett filter behöver utvärderas till sant för att funktionen ska aktiveras.
  • All innebär att varje filter måste utvärderas till sant för att funktionen ska aktiveras.

En requirement_type av All ändrar bläddringarna. Om det inte finns något filter inaktiveras funktionen. Om det finns filter bläddras funktionsfiltren igenom tills något av filtren beslutar att funktionen ska inaktiveras. Om inget filter anger att funktionen ska inaktiveras anses den vara aktiverad.

{
    "id": "FeatureW",
    "enabled": true,
    "conditions": {
        "requirement_type": "All",
        "client_filters": [
            {
                "name": "Microsoft.TimeWindow",
                "parameters": {
                    "Start": "Mon, 01 May 2023 13:59:59 GMT",
                    "End": "Sat, 01 Jul 2023 00:00:00 GMT"
                }
            },
            {
                "name": "Microsoft.Percentage",
                "parameters": {
                    "Value": "50"
                }
            }
        ]
    }
}

I exemplet ovan FeatureW anger en requirement_type av All, vilket innebär att alla dess filter måste utvärderas till true för att funktionen ska aktiveras. I det här fallet aktiveras funktionen för 50 % av användarna under den angivna tidsperioden.

.NET-funktionshanteringsschema

I tidigare versioner var det primära schemat för funktionshanteringsbiblioteket .NET feature management schema. Från och med v4.0.0 stöds inte nya funktioner som varianter och telemetri för .NET-funktionshanteringsschemat.

Kommentar

Om det finns en funktionsflaggadeklaration som finns i både avsnitten feature_management och FeatureManagement , kommer den från feature_management avsnittet att antas.

Förbrukning

Den grundläggande formen av funktionshantering är att kontrollera om en funktionsflagga är aktiverad och sedan utföra åtgärder baserat på resultatet. Detta görs via IFeatureManagermetoden 's IsEnabledAsync .

…
IFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
    // Do something
}

Tjänstregistrering

Funktionshantering förlitar sig på .NET Core-beroendeinmatning. Vi kan registrera funktionshanteringstjänster med hjälp av standardkonventioner.

using Microsoft.FeatureManagement;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddFeatureManagement();
    }
}

Som standard hämtar funktionshanteraren konfigurationen av funktionsflaggan från avsnittet "FeatureManagement" i .NET Core-konfigurationsdata. Om avsnittet "FeatureManagement" inte finns anses konfigurationen vara tom.

Kommentar

Du kan också ange att konfigurationen av funktionsflaggan ska hämtas från ett annat konfigurationsavsnitt genom att skicka avsnittet till AddFeatureManagement. I följande exempel uppmanas funktionshanteraren att läsa från ett annat avsnitt med namnet "MyFeatureFlags" i stället:

services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));

Beroendeinmatning

När du använder funktionshanteringsbiblioteket med MVC IFeatureManager kan du hämta det via beroendeinmatning.

public class HomeController : Controller
{
    private readonly IFeatureManager _featureManager;
    
    public HomeController(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }
}

Begränsade funktionshanteringstjänster

Metoden AddFeatureManagement lägger till funktionshanteringstjänster som singletons i programmet, men det finns scenarier där det kan vara nödvändigt att lägga till funktionshanteringstjänster som begränsade tjänster i stället. Användare kanske till exempel vill använda funktionsfilter som använder begränsade tjänster för kontextinformation. I det här fallet AddScopedFeatureManagement ska metoden användas i stället. Detta säkerställer att funktionshanteringstjänster, inklusive funktionsfilter, läggs till som begränsade tjänster.

services.AddScopedFeatureManagement();

ASP.NET Core-integrering

Funktionshanteringsbiblioteket innehåller funktioner i ASP.NET Core och MVC för att aktivera vanliga scenarier med funktionsflagga i webbprogram. De här funktionerna är tillgängliga genom att referera till NuGet-paketet Microsoft.FeatureManagement.AspNetCore .

Kontrollanter och åtgärder

MVC-styrenhet och åtgärder kan kräva att en viss funktion, eller en av alla listor över funktioner, aktiveras för att kunna köras. Detta kan göras med hjälp av en FeatureGateAttribute, som finns i Microsoft.FeatureManagement.Mvc namnområdet.

[FeatureGate("FeatureX")]
public class HomeController : Controller
{
    …
}

Ovanstående HomeController är gated av "FeatureX". "FeatureX" måste aktiveras innan någon åtgärd HomeController som innehåller kan köras.

[FeatureGate("FeatureX")]
public IActionResult Index()
{
    return View();
}

MVC-åtgärden Index ovan kräver att "FeatureX" aktiveras innan den kan köras.

Inaktiverad åtgärdshantering

När en MVC-styrenhet eller åtgärd blockeras eftersom ingen av de funktioner som anges är aktiverade anropas en registrerad IDisabledFeaturesHandler . Som standard registreras en minimalistisk hanterare som returnerar HTTP 404. Detta kan åsidosättas med hjälp av IFeatureManagementBuilder när du registrerar funktionsflaggor.

public interface IDisabledFeaturesHandler
{
    Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}

Visa

I MVC-vyer <feature> kan taggar användas för att villkorligt återge innehåll baserat på om en funktion är aktiverad eller inte.

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

Du kan också negera tagghjälputvärderingen för att visa innehåll när en funktion eller uppsättning funktioner inaktiveras. Genom att ange negate="true" i exemplet nedan återges innehållet endast om FeatureX det är inaktiverat.

<feature negate="true" name="FeatureX">
  <p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>

Taggen <feature> kan referera till flera funktioner genom att ange en kommaavgränsad lista över funktioner i name attributet.

<feature name="FeatureX,FeatureY">
  <p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>

Som standard måste alla listade funktioner vara aktiverade för att funktionstaggen ska återges. Det här beteendet kan åsidosättas genom att lägga till requirement attributet enligt exemplet nedan.

<feature name="FeatureX,FeatureY" requirement="Any">
  <p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>

I MVC-vyer <feature> kan taggar användas för att villkorligt återge innehåll baserat på om en funktion är aktiverad eller om en specifik variant av en funktion har tilldelats. Mer information finns i avsnittet varianter .

<feature name="FeatureX">
  <p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha">
  <p>This can only be seen if variant 'Alpha' of 'FeatureX' is assigned.</p>
</feature>

Du kan också negera tagghjälputvärderingen för att visa innehåll när en funktion eller uppsättning funktioner inaktiveras. Genom att ange negate="true" i exemplet nedan återges innehållet endast om FeatureX det är inaktiverat.

<feature negate="true" name="FeatureX">
  <p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
<feature negate="true" name="FeatureX" variant="Alpha">
  <p>This can only be seen if variant 'Alpha' of 'FeatureX' isn't assigned.</p>
</feature>

Taggen <feature> kan referera till flera funktioner/varianter genom att ange en kommaavgränsad lista över funktioner/varianter i name/variant attributet.

<feature name="FeatureX,FeatureY">
  <p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha,Beta">
  <p>This can only be seen if variant 'Alpha' or 'Beta' of 'FeatureX' is assigned.</p>
</feature>

Kommentar

Om variant anges ska endast en funktion anges.

Som standard måste alla listade funktioner vara aktiverade för att funktionstaggen ska återges. Det här beteendet kan åsidosättas genom att lägga till requirement attributet enligt exemplet nedan.

Kommentar

Om en requirement av And används tillsammans med variant ett fel genereras, eftersom flera varianter aldrig kan tilldelas.

<feature name="FeatureX,FeatureY" requirement="Any">
  <p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>

Taggen <feature> kräver en tag helper för att fungera. Detta kan göras genom att lägga till hjälpverktyget för funktionshanteringstaggen i filen ViewImports.cshtml .

@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

MVC-filter

MVC-åtgärdsfilter kan konfigureras för villkorlig körning baserat på tillståndet för en funktion. Detta görs genom att registrera MVC-filter på ett funktionsmedvetent sätt. Pipelinen för funktionshantering stöder asynkrona MVC-åtgärdsfilter som implementerar IAsyncActionFilter.

services.AddMvc(o => 
{
    o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});

Koden ovan lägger till ett MVC-filter med namnet SomeMvcFilter. Det här filtret utlöses endast i MVC-pipelinen om "FeatureX" är aktiverat.

Razor Pages

MVC Razor-sidor kan kräva att en viss funktion, eller en av alla listor över funktioner, aktiveras för att kunna köras. Detta kan göras med hjälp av en FeatureGateAttribute, som finns i Microsoft.FeatureManagement.Mvc namnområdet.

[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

Koden ovan konfigurerar en Razor-sida för att kräva att "FeatureX" aktiveras. Om funktionen inte är aktiverad genererar sidan ett HTTP 404-resultat (NotFound).

När det FeatureGateAttribute används på Razor-sidor måste det placeras på sidhanterartypen. Det kan inte placeras på enskilda hanteringsmetoder.

Programbygge

Funktionshanteringsbiblioteket kan användas för att lägga till programgrenar och mellanprogram som körs villkorligt baserat på funktionstillstånd.

app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");

Med ovanstående anrop lägger programmet till en mellanprogramskomponent som bara visas i begärandepipelinen om funktionen "FeatureX" är aktiverad. Om funktionen är aktiverad/inaktiverad under körningen kan pipelinen för mellanprogram ändras dynamiskt.

Detta bygger på den mer generiska funktionen för att förgrena hela programmet baserat på en funktion.

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

Implementera ett funktionsfilter

Genom att skapa ett funktionsfilter kan du aktivera funktioner baserat på kriterier som du definierar. För att implementera ett funktionsfilter IFeatureFilter måste gränssnittet implementeras. IFeatureFilter har en enda metod med namnet EvaluateAsync. När en funktion anger att den kan aktiveras för ett funktionsfilter EvaluateAsync anropas metoden. Om EvaluateAsync returnerar trueinnebär det att funktionen ska vara aktiverad.

Följande kodfragment visar hur du lägger till ett anpassat funktionsfilter MyCriteriaFilter.

services.AddFeatureManagement()
        .AddFeatureFilter<MyCriteriaFilter>();

Funktionsfilter registreras genom att anropa AddFeatureFilter<T> den IFeatureManagementBuilder som returneras från AddFeatureManagement. Dessa funktionsfilter har åtkomst till de tjänster som finns i tjänstsamlingen som användes för att lägga till funktionsflaggor. Beroendeinmatning kan användas för att hämta dessa tjänster.

Kommentar

När filter refereras i inställningar för funktionsflagga (till exempel appsettings.json) bör filterdelen av typnamnet utelämnas. Mer information finns i avsnittet Filter Alias Attribute .

Parameteriserade funktionsfilter

Vissa funktionsfilter kräver parametrar för att avgöra om en funktion ska vara aktiverad eller inte. Ett webbläsarfunktionsfilter kan till exempel aktivera en funktion för en viss uppsättning webbläsare. Det kan vara önskvärt att Edge- och Chrome-webbläsare aktiverar en funktion, medan Firefox inte gör det. För att göra detta kan ett funktionsfilter utformas för att förvänta sig parametrar. Dessa parametrar skulle anges i funktionskonfigurationen och i koden skulle vara tillgängliga via parametern FeatureFilterEvaluationContext 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; }
}

FeatureFilterEvaluationContext har en egenskap med namnet Parameters. De här parametrarna representerar en råkonfiguration som funktionsfiltret kan använda för att avgöra hur funktionen ska aktiveras eller inte. Om du vill använda webbläsarfunktionsfiltret som exempel igen kan filtret använda Parameters för att extrahera en uppsättning tillåtna webbläsare som skulle anges för funktionen och sedan kontrollera om begäran skickas från någon av dessa webbläsare.

[FilterAlias("Browser")]
public class BrowserFilter : IFeatureFilter
{
    …

    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
    {
        BrowserFilterSettings settings = context.Parameters.Get<BrowserFilterSettings>() ?? new BrowserFilterSettings();

        //
        // Here we would use the settings and see if the request was sent from any of BrowserFilterSettings.AllowedBrowsers
    }
}

Filteraliasattribut

När ett funktionsfilter registreras för en funktionsflagga är aliaset som används i konfigurationen namnet på funktionsfiltertypen med filtersuffixet, om det finns, borttaget. Till exempel MyCriteriaFilter skulle kallas MyCriteria i konfigurationen.

"MyFeature": {
    "EnabledFor": [
        {
            "Name": "MyCriteria"
        }
    ]
}

Detta kan åsidosättas med hjälp FilterAliasAttributeav . Ett funktionsfilter kan dekoreras med det här attributet för att deklarera det namn som ska användas i konfigurationen för att referera till det här funktionsfiltret i en funktionsflagga.

Funktionsfilter saknas

Om en funktion har konfigurerats för att aktiveras för ett specifikt funktionsfilter och funktionsfiltret inte är registrerat genereras ett undantag när funktionen utvärderas. Undantaget kan inaktiveras med hjälp av funktionshanteringsalternativen.

services.Configure<FeatureManagementOptions>(options =>
{
    options.IgnoreMissingFeatureFilters = true;
});

Använda HttpContext

Funktionsfilter kan utvärdera om en funktion ska aktiveras baserat på egenskaperna för en HTTP-begäran. Detta utförs genom att kontrollera HTTP-kontexten. Ett funktionsfilter kan hämta en referens till HTTP-kontexten genom att hämta en IHttpContextAccessor via beroendeinmatning.

public class BrowserFilter : IFeatureFilter
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public BrowserFilter(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }
}

IHttpContextAccessor Måste läggas till i containern för beroendeinmatning vid start för att den ska vara tillgänglig. Den kan registreras i med hjälp av IServiceCollection följande metod.

public void ConfigureServices(IServiceCollection services)
{
    …
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    …
}

Avancerat: IHttpContextAccessor/HttpContext bör inte användas i Razor-komponenterna i Blazor-appar på serversidan. Den rekommenderade metoden för att skicka http-kontext i Blazor-appar är att kopiera data till en begränsad tjänst. För Blazor-appar AddScopedFeatureManagement bör användas för att registrera funktionshanteringstjänster. Mer information finns i avsnittet Scoped Feature Management Services .

Ange en kontext för funktionsutvärdering

I konsolprogram finns det ingen omgivande kontext, HttpContext till exempel att funktionsfilter kan hämta och använda för att kontrollera om en funktion ska vara på eller av. I det här fallet måste program tillhandahålla ett objekt som representerar en kontext i funktionshanteringssystemet för användning av funktionsfilter. Detta görs med hjälp IFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext)av . AppContext-objektet som tillhandahålls till funktionshanteraren kan användas av funktionsfilter för att utvärdera tillståndet för en funktion.

MyAppContext context = new MyAppContext
{
    AccountId = current.Id;
}

if (await featureManager.IsEnabledAsync(feature, context))
{
…
}

Kontextuella funktionsfilter

Kontextuella funktionsfilter implementerar IContextualFeatureFilter<TContext> gränssnittet. Dessa särskilda funktionsfilter kan dra nytta av den kontext som skickas in när IFeatureManager.IsEnabledAsync<TContext> anropas. Typparametern TContext i IContextualFeatureFilter<TContext> beskriver vilken kontexttyp filtret kan hantera. På så sätt kan utvecklaren av ett kontextuellt funktionsfilter beskriva vad som krävs för dem som vill använda det. Eftersom varje typ är en underordnad objekttyp kan ett filter som implementerar anropas IContextualFeatureFilter<object> för valfri kontext. Om du vill illustrera ett exempel på ett mer specifikt kontextuellt funktionsfilter bör du överväga en funktion som är aktiverad om ett konto finns i en konfigurerad lista över aktiverade konton.

public interface IAccountContext
{
    string AccountId { get; set; }
}

[FilterAlias("AccountId")]
class AccountIdFilter : IContextualFeatureFilter<IAccountContext>
{
    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureEvaluationContext, IAccountContext accountId)
    {
        //
        // Evaluate if the feature should be on with the help of the provided IAccountContext
    }
}

Vi kan se att AccountIdFilter kräver ett objekt som implementeras IAccountContext för att kunna utvärdera tillståndet för en funktion. När du använder det här funktionsfiltret måste anroparen se till att det skickade objektet implementerar IAccountContext.

Kommentar

Endast ett enda funktionsfiltergränssnitt kan implementeras av en enda typ. Om du försöker lägga till ett funktionsfilter som implementerar mer än ett enda funktionsfiltergränssnitt resulterar det i en ArgumentException.

Använda kontextuella och icke-kontextuella filter med samma alias

Filter för IFeatureFilter och IContextualFeatureFilter kan dela samma alias. Mer specifikt kan du ha ett filteralias som delas av 0, 1 IFeatureFilter och 0 eller N IContextualFeatureFilter<ContextType>, så länge det finns högst ett tillämpligt filter för ContextType.

I följande avsnitt beskrivs processen för att välja ett filter när kontextuella och icke-kontextuella filter med samma namn registreras i ett program.

Anta att du har ett icke-kontextuellt filter som heter FilterA och två kontextuella filter FilterB och FilterC som accepterar TypeC TypeB respektive kontexter. Alla tre filtren delar samma alias SharedFilterName.

Du har också en funktionsflagga MyFeature som använder funktionsfiltret SharedFilterName i konfigurationen.

Om alla tre filtren är registrerade:

  • När du anropar IsEnabledAsync("MyFeature" FilterA används den för att utvärdera funktionsflaggan.
  • När du anropar IsEnabledAsync("MyFeature", kontext) används kontextens typ TypeB. FilterB Om kontextens typ är TypeCanvänds FilterC .
  • När du anropar IsEnabledAsync("MyFeature", kontext) används kontextens typ TypeF. FilterA

Inbyggda funktionsfilter

Det finns några funktionsfilter som medföljer Microsoft.FeatureManagement paketet: PercentageFilter, TimeWindowFilteroch ContextualTargetingFilter TargetingFilter. Alla filter, förutom TargetingFilter, läggs till automatiskt när funktionshantering registreras med AddFeatureManagement metod. TargetingFilter Läggs till med den WithTargeting metod som beskrivs i Targeting avsnittet nedan.

Vart och ett av de inbyggda funktionsfiltren har sina egna parametrar. Här är listan över funktionsfilter tillsammans med exempel.

Microsoft.Percentage

Det här filtret ger möjlighet att aktivera en funktion baserat på en angiven procentandel.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.Percentage",
            "Parameters": {
                "Value": 50
            }
        }
    ]
}

Microsoft.TimeWindow

Det här filtret ger möjlighet att aktivera en funktion baserat på ett tidsfönster. Om endast End anges betraktas funktionen som aktiverad fram till dess. Om endast Start anges beaktas funktionen på vid alla tidpunkter efter den tiden.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.TimeWindow",
            "Parameters": {
                "Start": "Wed, 01 May 2019 13:59:59 GMT",
                "End": "Mon, 01 Jul 2019 00:00:00 GMT"
            }
        }
    ]
}

Tidsfönstret kan konfigureras att upprepas regelbundet. Detta kan vara användbart för scenarier där man kan behöva aktivera en funktion under en låg eller hög trafikperiod på en dag eller vissa dagar i veckan. Om du vill expandera det enskilda tidsfönstret till återkommande tidsfönster bör upprepningsregeln anges i parametern Recurrence .

Kommentar

Start och End måste båda anges för att aktivera Recurrence.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "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"
                    }
                }
            }
        }
    ]
}

Recurrence Inställningarna består av två delar: Pattern (hur ofta tidsfönstret upprepas) och Range (hur länge upprepningsmönstret upprepas).

Återkommande mönster

Det finns två möjliga typer av upprepningsmönster: Daily och Weekly. Ett tidsfönster kan till exempel upprepa "varje dag", "var tredje dag", "varje måndag" eller "varannan fredag".

Beroende på typ krävs vissa fält Pattern , valfria eller ignoreras.

  • Daily

    Det dagliga upprepningsmönstret gör att tidsfönstret upprepas baserat på ett antal dagar mellan varje förekomst.

    Property Relevans beskrivning
    Typ Obligatoriskt Måste anges till Daily.
    Intervall Valfritt Anger antalet dagar mellan varje förekomst. Standardvärdet är 1.
  • Weekly

    Det veckovisa upprepningsmönstret gör att tidsfönstret upprepas samma dag eller dagar i veckan, baserat på antalet veckor mellan varje uppsättning förekomster.

    Property Relevans beskrivning
    Typ Obligatoriskt Måste anges till Weekly.
    DaysOfWeek Obligatoriskt Anger vilka dagar i veckan händelsen inträffar.
    Intervall Valfritt Anger antalet veckor mellan varje uppsättning förekomster. Standardvärdet är 1.
    FirstDayOfWeek Valfritt Anger vilken dag som anses vara den första dagen i veckan. Standardvärdet är Sunday.

    I följande exempel upprepas tidsfönstret varannan måndag och tisdag

    "Pattern": {
        "Type": "Weekly",
        "Interval": 2,
        "DaysOfWeek": ["Monday", "Tuesday"]
    }
    

Kommentar

Start måste vara en giltig första förekomst som passar upprepningsmönstret. Dessutom kan tidsfönstrets varaktighet inte vara längre än hur ofta det inträffar. Det är till exempel ogiltigt att ett 25-timmars tidsfönster upprepas varje dag.

Upprepningsintervall

Det finns tre möjliga typer av upprepningsintervall: NoEnd, EndDate och Numbered.

  • NoEnd

    Intervallet NoEnd gör att upprepningen sker på obestämd tid.

    Property Relevans beskrivning
    Typ Obligatoriskt Måste anges till NoEnd.
  • EndDate

    Intervallet EndDate gör att tidsfönstret inträffar på alla dagar som passar det tillämpliga mönstret fram till slutdatumet.

    Property Relevans beskrivning
    Typ Obligatoriskt Måste anges till EndDate.
    EndDate Obligatoriskt Anger datumtiden för att sluta tillämpa mönstret. Så länge starttiden för den senaste förekomsten infaller före slutdatumet tillåts sluttiden för den händelsen att sträcka sig längre än den.

    I följande exempel upprepas tidsfönstret varje dag tills den sista förekomsten inträffar den 1 april 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"
        }
    }
    
  • Numbered

    Intervallet Numbered gör att tidsfönstret inträffar ett fast antal gånger (baserat på mönstret).

    Property Relevans beskrivning
    Typ Obligatoriskt Måste anges till Numbered.
    NumberOfOccurrences Obligatoriskt Anger antalet förekomster.

    I följande exempel upprepas tidsfönstret på måndag och tisdag tills det finns tre förekomster, som inträffar den 1 april (mån), 2 april (tis) och 8 april (mån).

    "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
        }
    }
    

Om du vill skapa en upprepningsregel måste du ange både Pattern och Range. Alla mönstertyper kan fungera med valfri intervalltyp.

Avancerat: Tidszonsförskjutningen för Start egenskapen tillämpas på upprepningsinställningarna.

Microsoft.Targeting

Det här filtret ger möjlighet att aktivera en funktion för en målgrupp. En detaljerad förklaring av målinriktningen förklaras i målavsnittet nedan. Filterparametrarna innehåller ett Audience objekt som beskriver användare, grupper, exkluderade användare/grupper och en standardprocent av användarbasen som ska ha åtkomst till funktionen. Varje gruppobjekt som visas i Groups avsnittet måste också ange vilken procentandel av gruppens medlemmar som ska ha åtkomst. Om en användare anges i Exclusion avsnittet, antingen direkt eller om användaren finns i en exkluderad grupp, inaktiveras funktionen. Annars, om en användare anges direkt i Users avsnittet, eller om användaren är i den inkluderade procentandelen av någon av gruppdistributionerna, eller om användaren hamnar i standardprocenten för distribution kommer den användaren att ha funktionen aktiverad.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.Targeting",
            "Parameters": {
                "Audience": {
                    "Users": [
                        "Jeff",
                        "Alicia"
                    ],
                    "Groups": [
                        {
                            "Name": "Ring0",
                            "RolloutPercentage": 100
                        },
                        {
                            "Name": "Ring1",
                            "RolloutPercentage": 50
                        }
                    ],
                    "DefaultRolloutPercentage": 20,
                    "Exclusion": {
                        "Users": [
                            "Ross"
                        ],
                        "Groups": [
                            "Ring2"
                        ]
                    }
                }
            }
        }
    ]
}

Namnområden för funktionsfilteralias

Alla inbyggda funktionsfilteralias finns i namnområdet för funktionsfilter Microsoft . Detta för att förhindra konflikter med andra funktionsfilter som kan dela samma alias. Segmenten i ett namnområde för funktionsfilter delas med tecknet ".". Ett funktionsfilter kan refereras till av dess fullständigt kvalificerade alias, till exempel Microsoft.Percentage eller av det sista segmentet som i fallet Microsoft.Percentage med är Percentage.

Sök mål

Inriktning är en strategi för funktionshantering som gör det möjligt för utvecklare att successivt distribuera nya funktioner till sin användarbas. Strategin bygger på konceptet att rikta in sig på en uppsättning användare som kallas målgruppen. En målgrupp består av specifika användare, grupper, exkluderade användare/grupper och en angiven procentandel av hela användarbasen. De grupper som ingår i målgruppen kan delas upp ytterligare i procent av deras totala medlemmar.

Följande steg visar ett exempel på en progressiv distribution för en ny betafunktion:

  1. Enskilda användare Jeff och Alicia beviljas åtkomst till betaversionen
  2. En annan användare, Mark, ber om att få anmäla sig och ingår.
  3. Tjugo procent av en grupp som kallas "Ring1"-användare ingår i betaversionen.
  4. Antalet "Ring1"-användare som ingår i betaversionen ökas till 100 procent.
  5. Fem procent av användarbasen ingår i betaversionen.
  6. Distributionsprocenten ökar till 100 procent och funktionen distribueras helt.

Den här strategin för att lansera en funktion är inbyggd i biblioteket via det inkluderade funktionsfiltret Microsoft.Targeting .

Mål i ett webbprogram

Ett exempel på ett webbprogram som använder målfunktionsfiltret finns i exempelprojektet FeatureFlagDemo .

Om du vill börja använda TargetingFilter i ett program måste det läggas till i programmets tjänstsamling precis som andra funktionsfilter. Till skillnad från andra inbyggda filter TargetingFilter förlitar sig den på att en annan tjänst läggs till i programmets tjänstsamling. Tjänsten är en ITargetingContextAccessor.

Microsoft.FeatureManagement.AspNetCore tillhandahåller en standardimplementering ITargetingContextAccessor som extraherar målinformation från en begärans HttpContext. Du kan använda standardinställningen för kontextåtkomst när du konfigurerar mål med hjälp av den icke-generiska WithTargeting överlagringen på IFeatureManagementBuilder.

Standardinställningen för kontextåtkomst och TargetingFilter registreras genom att anropa WithTargetingIFeatureManagementBuilder.

services.AddFeatureManagement()
        .WithTargeting();

Du kan också registrera en anpassad implementering för ITargetingContextAccessor och TargetingFilter genom att anropa WithTargeting<T>. Här är ett exempel på hur du konfigurerar funktionshantering i ett webbprogram för att använda TargetingFilter med en implementering av ITargetingContextAccessor kallas ExampleTargetingContextAccessor.

services.AddFeatureManagement()
        .WithTargeting<ExampleTargetingContextAccessor>();

ITargetingContextAccessor

Om du vill använda TargetingFilter i ett webbprogram krävs en implementering av ITargetingContextAccessor . Detta beror på att när en målutvärdering utförs behövs kontextuell information, till exempel vilken användare som utvärderas för närvarande. Den här informationen kallas TargetingContext. Olika program kan extrahera den här informationen från olika platser. Några vanliga exempel på var ett program kan hämta målkontexten är begärans HTTP-kontext eller en databas.

Ett exempel som extraherar målkontextinformation från programmets HTTP-kontext är det DefaultHttpTargetingContextAccessor som tillhandahålls av Microsoft.FeatureManagement.AspNetCore paketet. Den extraherar målinformation från HttpContext.User. UserId informationen extraheras från fältet Identity.Name och Groups informationen extraheras från anspråk av typen Role. Den här implementeringen bygger på användningen av IHttpContextAccessor, som beskrivs här.

Mål i ett konsolprogram

Målfiltret förlitar sig på en målkontext för att utvärdera om en funktion ska aktiveras. Den här målkontexten innehåller information som vilken användare som utvärderas för närvarande och vilka grupper användaren i. I konsolprogram finns det vanligtvis ingen omgivande kontext tillgänglig för att flöda den här informationen till målfiltret. Därför måste den skickas direkt när FeatureManager.IsEnabledAsync den anropas. Detta stöds med hjälp ContextualTargetingFilterav . Program som behöver flytta målkontexten till funktionshanteraren bör använda detta i stället för TargetingFilter.

Eftersom ContextualTargetingFilter är en IContextualTargetingFilter<ITargetingContext>måste en implementering av ITargetingContext skickas in för att IFeatureManager.IsEnabledAsync den ska kunna utvärdera och aktivera en funktion.

IFeatureManager fm;
…
// userId and groups defined somewhere earlier in application
TargetingContext targetingContext = new TargetingContext
{
   UserId = userId,
   Groups = groups
};

await fm.IsEnabledAsync(featureName, targetingContext);

Använder ContextualTargetingFilter fortfarande funktionsfilteraliaset Microsoft.Targeting, så konfigurationen för det här filtret överensstämmer med vad som nämns i det avsnittet.

Ett exempel som använder ContextualTargetingFilter i ett konsolprogram är tillgängligt i exempelprojektet TargetingConsoleApp .

Mål för utvärderingsalternativ

Det finns alternativ för att anpassa hur målutvärdering utförs för alla funktioner. Dessa alternativ kan konfigureras när du konfigurerar funktionshantering.

services.Configure<TargetingEvaluationOptions>(options =>
{
    options.IgnoreCase = true;
});

Målundantag

När du definierar en målgrupp kan användare och grupper undantas från målgruppen. Detta är användbart när en funktion distribueras till en grupp användare, men några användare eller grupper måste undantas från distributionen. Exkludering definieras genom att en lista över användare och grupper läggs till i målgruppens Exclusion egenskap.

"Audience": {
    "Users": [
        "Jeff",
        "Alicia"
    ],
    "Groups": [
        {
            "Name": "Ring0",
            "RolloutPercentage": 100
        }
    ],
    "DefaultRolloutPercentage": 0
    "Exclusion": {
        "Users": [
            "Mark"
        ]
    }
}

I exemplet ovan är funktionen aktiverad för användare med namnet Jeff och Alicia. Det är också aktiverat för användare i gruppen med namnet Ring0. Men om användaren heter Markinaktiveras funktionen, oavsett om de finns i gruppen Ring0 eller inte. Undantag prioriteras framför resten av målfiltret.

Varianter

När nya funktioner läggs till i ett program kan det hända att en funktion har flera olika föreslagna designalternativ. En vanlig lösning för att bestämma en design är någon form av A/B-testning, vilket innebär att tillhandahålla en annan version av funktionen till olika segment av användarbasen och välja en version baserat på användarinteraktion. I det här biblioteket aktiveras den här funktionen genom att representera olika konfigurationer av en funktion med varianter.

Varianter gör det möjligt för en funktionsflagga att bli mer än en enkel på/av-flagga. En variant representerar ett värde för en funktionsflagga som kan vara en sträng, ett tal, ett booleskt objekt eller till och med ett konfigurationsobjekt. En funktionsflagga som deklarerar varianter bör definiera under vilka omständigheter varje variant ska användas, vilket beskrivs mer detaljerat i avsnittet Allokera varianter .

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; }
}

Hämta varianter

För varje funktion kan en variant hämtas med metoden IVariantFeatureManager's GetVariantAsync .

…
IVariantFeatureManager featureManager;
…
Variant variant = await featureManager.GetVariantAsync(MyFeatureFlags.FeatureU, CancellationToken.None);

IConfigurationSection variantConfiguration = variant.Configuration;

// Do something with the resulting variant and its configuration

När en variant har hämtats kan konfigurationen av en variant användas direkt som en IConfigurationSection från variantens Configuration egenskap. Ett annat alternativ är att binda konfigurationen till ett objekt med hjälp av . NET:s konfigurationsbindningsmönster.

IConfigurationSection variantConfiguration = variant.Configuration;

MyFeatureSettings settings = new MyFeatureSettings();

variantConfiguration.Bind(settings);

Varianten som returneras är beroende av att användaren för närvarande utvärderas och att informationen hämtas från en instans av TargetingContext. Den här kontexten kan antingen skickas när du anropar GetVariantAsync eller så kan den hämtas automatiskt från en implementering av ITargetingContextAccessor om en är registrerad.

Deklaration av variantfunktionsflagga

Jämfört med normala funktionsflaggor har variantfunktionsflaggor ytterligare två egenskaper: variants och allocation. Egenskapen variants är en matris som innehåller de varianter som definierats för den här funktionen. Egenskapen allocation definierar hur dessa varianter ska allokeras för funktionen. Precis som när du deklarerar normala funktionsflaggor kan du konfigurera variantfunktionsflaggor i en json-fil. Här är ett exempel på en variantfunktionsflagga.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "enabled": true,
                "allocation": {
                    "default_when_enabled": "Small",
                    "group": [
                        {
                            "variant": "Big",
                            "groups": [
                                "Ring1"
                            ]
                        }
                    ]
                },
                "variants": [
                    { 
                        "name": "Big"
                    },  
                    { 
                        "name": "Small"
                    } 
                ]
            }
        ]
    }
}

Definiera varianter

Varje variant har två egenskaper: ett namn och en konfiguration. Namnet används för att referera till en specifik variant och konfigurationen är värdet för den varianten. Konfigurationen kan anges med hjälp av configuration_value egenskapen . configuration_value är en infogad konfiguration som kan vara ett sträng-, tal-, booleskt eller konfigurationsobjekt. Om configuration_value inte anges är den returnerade variantens Configuration egenskap null.

En lista över alla möjliga varianter definieras för varje funktion under egenskapen variants .

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "variants": [
                    { 
                        "name": "Big", 
                        "configuration_value": {
                            "Size": 500
                        }
                    },  
                    { 
                        "name": "Small", 
                        "configuration_value": {
                            "Size": 300
                        }
                    } 
                ]
            }
        ]
    }
}

Allokera varianter

Processen för att allokera en funktions varianter bestäms av allocation funktionens egenskap.

"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"
    } 
]

Inställningen allocation för en funktion har följande egenskaper:

Property beskrivning
default_when_disabled Anger vilken variant som ska användas när en variant begärs medan funktionen anses vara inaktiverad.
default_when_enabled Anger vilken variant som ska användas när en variant begärs medan funktionen anses vara aktiverad och ingen annan variant har tilldelats användaren.
user Anger en variant och en lista över användare som den varianten ska tilldelas till.
group Anger en variant och en lista över grupper. Varianten tilldelas om användaren finns i minst en av grupperna.
percentile Anger en variant och ett procentintervall som användarens beräknade procentandel måste passa in i för att den varianten ska tilldelas.
seed Värdet som procentberäkningar för percentile baseras på. Procentberäkningen för en viss användare blir densamma för alla funktioner om samma seed värde används. Om inget seed anges skapas ett standardutsäde baserat på funktionsnamnet.

Om funktionen inte är aktiverad i exemplet ovan tilldelar funktionshanteraren den variant som markerats som default_when_disabled till den aktuella användaren, vilket i det här fallet är Small fallet.

Om funktionen är aktiverad kontrollerar funktionshanteraren allokeringarna user, groupoch percentile i den ordningen för att tilldela en variant. I det här exemplet, om användaren som utvärderas heter Marsha, i gruppen med namnet Ring1, eller om användaren råkar falla mellan 0 och 10:e percentilen, tilldelas den angivna varianten till användaren. I det här fallet returnerar alla dessa varianten Big . Om ingen av dessa allokeringar matchar tilldelas användaren varianten default_when_enabled , som är Small.

Allokeringslogik liknar funktionsfiltret Microsoft.Targeting , men det finns vissa parametrar som finns i mål som inte finns i allokering och vice versa. Resultatet av mål och allokering är inte relaterade.

Kommentar

Om du vill tillåta allokering av funktionsvarianter måste du registrera ITargetingContextAccessor. Detta kan göras genom att anropa WithTargeting<T> metoden.

Åsidosätta aktiverat tillstånd med en variant

Du kan använda varianter för att åsidosätta det aktiverade tillståndet för en funktionsflagga. Detta ger varianter en möjlighet att utöka utvärderingen av en funktionsflagga. När du anropar IsEnabled en flagga med varianter kontrollerar funktionshanteraren om den variant som tilldelats den aktuella användaren har konfigurerats för att åsidosätta resultatet. Detta görs med hjälp av den valfria variantegenskapen status_override. Som standard är den här egenskapen inställd på None, vilket innebär att varianten inte påverkar om flaggan anses vara aktiverad eller inaktiverad. Inställningen status_override tillåter att Enabled varianten, när den väljs, åsidosätter en flagga som ska aktiveras. Inställningen status_override ger Disabled motsatt funktionalitet och inaktiverar därför flaggan när varianten väljs. En funktion med tillståndet enabled false kan inte åsidosättas.

Om du använder en funktionsflagga med binära varianter kan egenskapen status_override vara till stor hjälp. Det gör att du kan fortsätta använda API:er som IsEnabledAsync och FeatureGateAttribute i ditt program, samtidigt som du drar nytta av de nya funktionerna som medföljer varianter, till exempel percentilallokering och seed.

{
    "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"
        }
    ]
}

I exemplet ovan är funktionen alltid aktiverad. Om den aktuella användaren är i det beräknade percentilintervallet på 10 till 20 returneras varianten On . Annars returneras varianten Off och eftersom status_override är lika Disabledmed betraktas funktionen nu som inaktiverad.

Varianter i beroendeinmatning

Variantfunktionsflaggor kan användas tillsammans med beroendeinmatning för att visa olika implementeringar av en tjänst för olika användare. Detta görs med hjälp IVariantServiceProvider<TService> av gränssnittet.

IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...

IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken); 

I kodfragmentet ovan IVariantServiceProvider<IAlgorithm> hämtar en implementering av IAlgorithm från containern för beroendeinmatning. Den valda implementeringen är beroende av:

  • Funktionsflaggan IAlgorithm som tjänsten registrerades med.
  • Den allokerade varianten för den funktionen.

IVariantServiceProvider<T> Görs tillgänglig för programmet genom att anropa IFeatureManagementBuilder.WithVariantService<T>(string featureName). Nedan visas ett exempel.

services.AddFeatureManagement() 
        .WithVariantService<IAlgorithm>("ForecastAlgorithm");

Anropet ovan gör IVariantServiceProvider<IAlgorithm> tillgängligt i tjänstsamlingen. Implementeringar av IAlgorithm måste läggas till separat via en tilläggsmetod som services.AddSingleton<IAlgorithm, SomeImplementation>(). Implementeringen av IAlgorithm användningarna IVariantServiceProvider beror på ForecastAlgorithm variantfunktionsflaggan. Om ingen implementering av IAlgorithm läggs till i tjänstsamlingen returnerar uppgiften IVariantServiceProvider<IAlgorithm>.GetServiceAsync() ett null-resultat .

{
    // The example variant feature flag
    "id": "ForecastAlgorithm",
    "enabled": true,
    "variants": [
        { 
            "Name": "AlgorithmBeta" 
        },
        ...
    ] 
}

Aliasattribut för varianttjänst

[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
    ...
}

Varianttjänstleverantören använder typnamnen för implementeringar för att matcha den allokerade varianten. Om en varianttjänst är dekorerad med VariantServiceAliasAttributeska namnet som deklareras i det här attributet användas i konfigurationen för att referera till den här varianttjänsten.

Telemetri

När en ändring av funktionsflaggan distribueras är det ofta viktigt att analysera dess effekt på ett program. Här är till exempel några frågor som kan uppstå:

  • Är mina flaggor aktiverade/inaktiverade som förväntat?
  • Får målanvändare åtkomst till en viss funktion som förväntat?
  • Vilken variant ser en viss användare?

Dessa typer av frågor kan besvaras genom utsläpp och analys av funktionsflaggans utvärderingshändelser. Det här biblioteket använder API:et System.Diagnostics.Activity för att producera spårningstelemetri under utvärdering av funktionsflagga.

Aktivera telemetri

Som standard har funktionsflaggor ingen telemetri genererad. Om du vill publicera telemetri för en viss funktionsflagga måste flaggan deklarera att den är aktiverad för telemetriutsläpp.

För funktionsflaggor som definieras i appsettings.jsongörs detta med hjälp telemetry av egenskapen .

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyFeatureFlag",
                "enabled": true,
                "telemetry": {
                    "enabled": true
                }
            }
        ]
    }
}

Kodfragmentet appsettings ovan definierar en funktionsflagga med namnet MyFeatureFlag som är aktiverad för telemetri. Detta indikeras av det telemetry objekt som anges enabled till sant. Värdet för egenskapen enabled måste vara true att publicera telemetri för flaggan.

Avsnittet telemetry i en funktionsflagga har följande egenskaper:

Property beskrivning
enabled Anger om telemetri ska publiceras för funktionsflaggan.
metadata En samling nyckel/värde-par, modellerade som en ordlista, som kan användas för att bifoga anpassade metadata om funktionsflaggan till utvärderingshändelser.

Anpassad telemetripublicering

Funktionshanteraren har sitt eget ActivitySource namn "Microsoft.FeatureManagement". Om telemetry är aktiverat för en funktionsflagga startar funktionshanteraren en när utvärderingen av funktionsflaggan startas Activity. När utvärderingen av funktionsflaggan är klar lägger funktionshanteraren till en ActivityEvent namngiven FeatureFlag till den aktuella aktiviteten. Händelsen FeatureFlag har taggar som innehåller information om funktionsflaggans utvärdering, enligt de fält som definierats i FeatureEvaluationEvent-schemat .

Kommentar

Alla nyckelvärdepar som anges i telemetry.metadata funktionsflaggan inkluderas också i taggarna.

Om du vill aktivera anpassad telemetripublicering kan du skapa en ActivityListener och lyssna på aktivitetskällan Microsoft.FeatureManagement . Här är ett exempel som visar hur du lyssnar på aktivitetskällan för funktionshantering och lägger till ett återanrop när en funktion utvärderas.

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.
        }
    }
});

Mer information finns i Samla in en distribuerad spårning.

Application Insights Telemetry Publisher

Paketet Microsoft.FeatureManagement.Telemetry.ApplicationInsights innehåller en inbyggd telemetriutgivare som skickar utvärderingsdata för funktionsflaggan till Application Insights. Om du vill dra nytta av detta lägger du till en referens till paketet och registrerar Application Insights-telemetriutgivaren enligt nedan.

builder.services
    .AddFeatureManagement()
    .AddApplicationInsightsTelemetryPublisher();

Paketet Microsoft.FeatureManagement.Telemetry.ApplicationInsights tillhandahåller en telemetriinitierare som automatiskt taggar alla händelser med TargetingId så att händelser kan länkas till flaggutvärderingar. Om du vill använda telemetriinitieraren TargetingTelemetryInitializerlägger du till den i programmets tjänstsamling.

builder.Services.AddSingleton<ITelemetryInitializer, TargetingTelemetryInitializer>();

Kommentar

För att säkerställa att fungerar TargetingTelemetryInitializer som förväntat bör du använda beskrivningen TargetingHttpContextMiddleware nedan.

Om du vill aktivera kvarstående målkontext i den aktuella aktiviteten kan du använda TargetingHttpContextMiddleware.

app.UseMiddleware<TargetingHttpContextMiddleware>();

Ett exempel på dess användning finns i exemplet VariantAndTelemetryDemo .

Förutsättningar

Den här telemetriutgivaren är beroende av att Application Insights redan har konfigurerats som en programtjänst. Det görs till exempel här i exempelprogrammet.

Den här telemetriutgivaren är beroende av att Application Insights redan har konfigurerats och registrerats som en programtjänst.

Cachelagring

Funktionstillstånd tillhandahålls av IConfiguration systemet. Eventuell cachelagring och dynamisk uppdatering förväntas hanteras av konfigurationsprovidrar. Funktionshanteraren ber om IConfiguration det senaste värdet för en funktions tillstånd när en funktion kontrolleras för att aktiveras.

Ögonblicksbild

Det finns scenarier som kräver att tillståndet för en funktion förblir konsekvent under en begärans livslängd. Värdena som returneras från standarden IFeatureManager kan ändras om källan IConfiguration som den hämtas från uppdateras under begäran. Detta kan förhindras med hjälp IFeatureManagerSnapshotav . IFeatureManagerSnapshot kan hämtas på samma sätt som IFeatureManager. IFeatureManagerSnapshot implementerar gränssnittet IFeatureManagerför , men cachelagrar det första utvärderade tillståndet för en funktion under en begäran och returnerar samma tillstånd för en funktion under dess livslängd.

Anpassade funktionsprovidrar

Genom att implementera en anpassad funktionsprovider kan utvecklare hämta funktionsflaggor från källor som en databas eller en funktionshanteringstjänst. Den inkluderade funktionsprovidern som används som standard hämtar funktionsflaggor från .NET Cores konfigurationssystem. Detta gör att funktioner kan definieras i en appsettings.json-fil eller i konfigurationsleverantörer som Azure App Configuration. Det här beteendet kan ersättas för att ge fullständig kontroll över var funktionsdefinitioner läse från.

Om du vill anpassa inläsningen av funktionsdefinitioner måste du implementera IFeatureDefinitionProvider gränssnittet.

public interface IFeatureDefinitionProvider
{
    Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);

    IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}

Om du vill använda en implementering av IFeatureDefinitionProvidermåste den läggas till i tjänstsamlingen innan du lägger till funktionshantering. I följande exempel läggs en implementering av IFeatureDefinitionProvider med namnet InMemoryFeatureDefinitionProvider.

services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
        .AddFeatureManagement()

Nästa steg

Om du vill lära dig hur du använder funktionsflaggor i dina program fortsätter du till följande snabbstarter.

Om du vill lära dig hur du använder funktionsfilter fortsätter du till följande självstudier.

Om du vill lära dig hur du kör experiment med olika funktionsflaggor fortsätter du till följande självstudie.