.NET-Featureverwaltung
Die .NET-Featureverwaltungsbibliothek bietet eine Möglichkeit, Anwendungsfunktionen basierend auf Featurekennzeichnungen zu entwickeln und verfügbar zu machen. Sobald ein neues Feature entwickelt wurde, haben viele Anwendungen spezielle Anforderungen, z. B. wann das Feature aktiviert werden soll und unter welchen Bedingungen. Diese Bibliothek bietet eine Möglichkeit, diese Beziehungen zu definieren und auch in gängige .NET-Codemuster zu integrieren, um diese Features verfügbar zu machen.
Featurekennzeichnungen bieten eine Möglichkeit für .NET und ASP.NET Core-Anwendungen, Features dynamisch zu aktivieren oder zu deaktivieren. Entwickler können Featurekennzeichnungen in einfachen Anwendungsfällen wie bedingten Anweisungen für komplexere Szenarien wie das Hinzufügen von Routen oder MVC-Filtern verwenden. Featurekennzeichnungen basieren auf dem .NET Core-Konfigurationssystem. Jeder .NET Core-Konfigurationsanbieter kann als Backbone für Featurekennzeichnungen fungieren.
Hier sind einige der Vorteile der Verwendung der .NET-Featureverwaltungsbibliothek:
Eine allgemeine Konvention für die Featureverwaltung
Niedrige Einstiegsbarriere
- Basiert auf
IConfiguration
- Unterstützt das Einrichten von JSON-Dateifeatures
- Basiert auf
Verwaltung der Featurekennzeichnungslebensdauer
- Konfigurationswerte können sich in Echtzeit ändern; Featurekennzeichnungen können für die gesamte Anforderung konsistent sein
Behandelte einfache bis komplexe Szenarien
- Aktivieren/Deaktivieren von Features durch deklarative Konfigurationsdatei
- Dynamische Auswertung des Funktionsstatus basierend auf dem Aufruf an den Server
API-Erweiterungen für ASP.NET Core- und MVC-Framework
- Routing
- Filter
- Aktionsattribute
Die .NET-Featureverwaltungsbibliothek ist Open Source. Weitere Informationen finden Sie im GitHub-Repository.
Featurekennzeichnungen
Featurekennzeichnungen bestehen aus zwei Teilen, einem Namen und einer Liste von Featurefiltern, die zum Aktivieren des Features verwendet werden.
Featurefilter
Featurefilter definieren ein Szenario, für das ein Feature aktiviert werden soll. Wenn ein Feature ausgewertet wird, egal ob es aktiviert oder deaktiviert ist, wird die Liste der Featurefilter durchlaufen, bis einer der Filter entscheidet, dass das Feature aktiviert werden soll. An diesem Punkt gilt das Feature als aktiviert und der Durchlauf der Featurefilter endet. Wenn kein Featurefilter angibt, dass das Feature aktiviert werden soll, gilt es als deaktiviert.
Beispielsweise könnte ein Microsoft Edge-Browserfeaturefilter entworfen werden. Dieser Featurefilter aktiviert alle Features, an die es angefügt ist, solange eine HTTP-Anforderung von Microsoft Edge stammt.
Featurekennzeichnungskonfiguration
Das .NET Core-Konfigurationssystem wird verwendet, um den Status von Featurekennzeichnungen zu bestimmen. Die Grundlage dieses Systems ist IConfiguration
. Jeder Anbieter für IConfiguration
kann als Featurestatusanbieter für die Featurekennzeichnungsbibliothek verwendet werden. Dieses System ermöglicht Szenarien, die von appsettings.json bis hin zur Azure-App-Konfiguration und mehr reichen.
Featureflagdeklaration
Die Featureverwaltungsbibliothek unterstützt appsettings.json als Featurekennzeichnungsquelle, da sie ein Anbieter für das IConfiguration
-System von .NET Core ist. Nachfolgend finden Sie ein Beispiel für das Format, das zum Einrichten von Featurekennzeichnungen in einer JSON-Datei verwendet wird.
{
"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"
}
}
]
}
}
}
Der FeatureManagement
-Abschnitt des JSON-Dokuments wird konventionsspezifisch zum Laden von Featurekennzeichnungseinstellungen verwendet. Im Abschnitt oben sehen wir drei verschiedene Features. Features definieren ihre Featurefilter mithilfe der EnabledFor
-Eigenschaft. In den Featurefiltern für FeatureT
wird AlwaysOn
angezeigt. Dieser Featurefilter ist integriert, und wenn angegeben, aktiviert er das Feature immer. Der AlwaysOn
-Featurefilter erfordert keine Konfiguration, sodass er nur über die Name
-Eigenschaft verfügt. FeatureU
hat keine Filter in seiner EnabledFor
-Eigenschaft und wird daher nie aktiviert. Auf alle Funktionen, die auf diesem aktivierten Feature basieren, kann nicht zugegriffen werden, solange die Featurefilter leer bleiben. Sobald jedoch ein Featurefilter hinzugefügt wird, der das Feature aktiviert, kann er mit der Arbeit beginnen. FeatureV
gibt einen Featurefilter mit dem Namen TimeWindow
an. Dies ist ein Beispiel für einen konfigurierbaren Featurefilter. Wir können im Beispiel sehen, dass der Filter über eine Parameters
-Eigenschaft verfügt. Diese wird verwendet, um den Filter zu konfigurieren. In diesem Fall werden die Start- und Endzeiten für das zu aktive Feature konfiguriert.
Das detaillierte Schema des FeatureManagement
-Abschnitts finden Sie hier.
Erweitert: Die Verwendung des Doppelpunkts ":" ist in Featurekennzeichnungsnamen verboten.
On/Off-Deklaration
Der folgende Codeausschnitt veranschaulicht eine alternative Möglichkeit zum Definieren eines Features, das für Ein-/Aus-Features verwendet werden kann.
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
// Define feature flags in config file
"FeatureManagement": {
"FeatureT": true, // On feature
"FeatureX": false // Off feature
}
}
RequirementType
Die RequirementType
-Eigenschaft einer Featurekennzeichnung wird verwendet, um zu bestimmen, ob die Filter Any
- oder All
-Logik zum Auswerten des Status eines Features verwenden sollen. Wenn RequirementType
nicht angegeben ist, wird der Standardwert Any
.
Any
bedeutet, dass nur ein Filter als „true“ ausgewertet werden muss, damit das Feature aktiviert wird.All
bedeutet, dass jeder Filter als „true“ ausgewertet werden muss, damit das Feature aktiviert wird.
Eine RequirementType
von All
ändert das Traversal. Wenn keine Filter vorhanden sind, ist das Feature deaktiviert. Anschließend werden die Featurefilter durchlaufen, bis einer der Filter entscheidet, dass das Feature deaktiviert werden soll. Wenn kein Filter angibt, dass das Feature deaktiviert werden soll, wird es als aktiviert betrachtet.
"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"
}
}
]
}
Im obigen Beispiel gibt FeatureW
eine RequirementType
von All
an, was bedeutet, dass alle Filter als „true“ ausgewertet werden müssen, damit das Feature aktiviert werden kann. In diesem Fall ist das Feature für 50 % der Benutzer im angegebenen Zeitfenster aktiviert.
Microsoft Feature Management-Schema
Die Featureverwaltungsbibliothek unterstützt auch die Verwendung von Microsoft Feature Management schema
zum Deklarieren von Featurekennzeichen. Dieses Schema ist sprachunabhängig im Ursprung und wird von allen Microsoft-Featureverwaltungsbibliotheken unterstützt.
{
"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"
}
}
]
}
}
]
}
}
Hinweis
Wenn der feature_management
-Abschnitt in der Konfiguration gefunden werden kann, wird der FeatureManagement
-Abschnitt ignoriert.
Die Featureverwaltungsbibliothek unterstützt appsettings.json als Featurekennzeichnungsquelle, da sie ein Anbieter für das IConfiguration
-System von .NET Core ist. Featurekennzeichnungen werden mithilfe der Microsoft Feature Management schema
deklariert. Dieses Schema ist sprachunabhängig im Ursprung und wird von allen Microsoft-Featureverwaltungsbibliotheken unterstützt.
Nachfolgend finden Sie ein Beispiel zum Deklarieren von Featurekennzeichnungen in einer JSON-Datei.
{
"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"
}
}
]
}
}
]
}
}
Der feature_management
-Abschnitt des JSON-Dokuments wird konventionsspezifisch zum Laden von Featurekennzeichnungseinstellungen verwendet. Featurekennzeichnungsobjekte müssen im feature_flags
-Array unter dem feature_management
-Abschnitt aufgeführt werden. Im Abschnitt oben sehen wir, dass wir drei verschiedene Features bereitgestellt haben. Eine Featurekennzeichnung hat id
- und enabled
-Eigenschaften. Der id
ist der Name, der zum Identifizieren und Verweisen auf die Featurekennzeichnung verwendet wird. Die enabled
-Eigenschaft gibt den aktivierten Status der Featurekennzeichnung an. Ein Feature ist DEAKTIVIERT, wenn enabled
„false“ ist. Wenn enabled
„true“ ist, hängt der Status des Features von der conditions
ab. Wenn kein conditions
-Feature vorhanden ist, ist das Feature EIN. Wenn conditions
vorhanden sind und sie erfüllt sind, ist das Feature EIN. Wenn conditions
vorhanden sind und sie nicht erfüllt sind, ist das Feature AUS. Die conditions
-Eigenschaft deklariert die Bedingungen, die zum dynamischen Aktivieren des Features verwendet werden. Features definieren ihre Featurefilter im client_filters
-Array. FeatureV
gibt einen Featurefilter mit dem Namen Microsoft.TimeWindow
an. Dies ist ein Beispiel für einen konfigurierbaren Featurefilter. Wir können im Beispiel sehen, dass der Filter über eine Parameters
-Eigenschaft verfügt. Diese wird verwendet, um den Filter zu konfigurieren. In diesem Fall werden die Start- und Endzeiten für das zu aktive Feature konfiguriert.
Erweitert: Die Verwendung des Doppelpunkts ":" ist in Featurekennzeichnungsnamen verboten.
RequirementType
Die requirement_type
-Eigenschaft von conditions
wird verwendet, um zu ermitteln, ob die Filter Any
- oder All
-Logik zum Auswerten des Status eines Features verwenden sollen. Wenn requirement_type
nicht angegeben ist, wird der Standardwert Any
.
Any
bedeutet, dass nur ein Filter als „true“ ausgewertet werden muss, damit das Feature aktiviert wird.All
bedeutet, dass jeder Filter als „true“ ausgewertet werden muss, damit das Feature aktiviert wird.
Eine requirement_type
von All
ändert das Traversal. Wenn kein Filter vorhanden ist, wird das Feature deaktiviert. Wenn Filter vorhanden sind, werden die Featurefilter durchlaufen, bis eines der Filter entscheidet, dass das Feature deaktiviert werden soll. Wenn kein Filter angibt, dass das Feature deaktiviert werden soll, wird es als aktiviert betrachtet.
{
"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"
}
}
]
}
}
Im obigen Beispiel gibt FeatureW
eine requirement_type
von All
an, was bedeutet, dass alle Filter als „true“ ausgewertet werden müssen, damit das Feature aktiviert werden kann. In diesem Fall wird das Feature für 50 % der Benutzer im angegebenen Zeitfenster aktiviert.
.NET-Featureverwaltungsschema
In früheren Versionen war das primäre Schema für die Featureverwaltungsbibliothek die .NET feature management schema
. Ab v4.0.0 werden neue Features, einschließlich Varianten und Telemetrie, für das .NET-Featureverwaltungsschema nicht unterstützt.
Hinweis
Wenn es eine Deklaration für Featureflags gibt, die sowohl im Abschnitt feature_management
als auch FeatureManagement
zu finden ist, wird die Deklaration des Abschnitts feature_management
übernommen.
Verbrauch
Die grundlegende Form der Featureverwaltung überprüft, ob eine Featurekennzeichnung aktiviert ist und führt dann Aktionen basierend auf dem Ergebnis aus. Dies erfolgt über die IsEnabledAsync
-Methode von IFeatureManager
.
…
IFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
// Do something
}
Dienstregistrierung
Die Featureverwaltung basiert auf .NET Core-Abhängigkeitsinjektion. Wir können Featureverwaltungsdienste unter Verwendung von Standardkonventionen registrieren.
using Microsoft.FeatureManagement;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement();
}
}
Der Featureverwalter ruft die Featurekennzeichnungskonfiguration standardmäßig aus dem Abschnitt „FeatureManagement“ der .NET Core-Konfigurationsdaten ab. Wenn der Abschnitt „FeatureManagement“ nicht vorhanden ist, wird die Konfiguration als leer betrachtet.
Hinweis
Sie können auch angeben, dass die Featurekennzeichnungskonfiguration aus einem anderen Konfigurationsabschnitt abgerufen werden soll, indem Sie den Abschnitt an AddFeatureManagement
übergeben. Im folgenden Beispiel wird der Featureverwalter aufgefordert, stattdessen aus einem anderen Abschnitt namens "“MyFeatureFlags“ zu lesen:
services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));
Dependency Injection
Wenn Sie die Featureverwaltungsbibliothek mit MVC verwenden, kann die IFeatureManager
über die Abhängigkeitsinjektion abgerufen werden.
public class HomeController : Controller
{
private readonly IFeatureManager _featureManager;
public HomeController(IFeatureManager featureManager)
{
_featureManager = featureManager;
}
}
Bereichsbezogene Featureverwaltungsdienste
Die AddFeatureManagement
-Methode fügt Featureverwaltungsdienste als Singletons innerhalb der Anwendung hinzu, aber es gibt Szenarien, in denen es erforderlich sein kann, dass Featureverwaltungsdienste stattdessen als bereichsbezogene Dienste hinzugefügt werden. Benutzer können beispielsweise Featurefilter verwenden, die bereichsbezogene Dienste für Kontextinformationen nutzen. In diesem Fall sollte die AddScopedFeatureManagement
-Methode stattdessen verwendet werden. Dadurch wird sichergestellt, dass Featureverwaltungsdienste, einschließlich Featurefiltern, als bereichsbezogene Dienste hinzugefügt werden.
services.AddScopedFeatureManagement();
ASP.NET-Kernintegration
Die Featureverwaltungsbibliothek bietet Funktionen in ASP.NET Core und MVC, um allgemeine Featurekennzeichnungsszenarien in Webanwendungen zu ermöglichen. Diese Funktionen sind verfügbar, indem sie auf das Microsoft.FeatureManagement.AspNetCore-NuGet-Paket verweisen.
Controller und Aktionen
MVC-Controller und -Aktionen können erfordern, dass ein bestimmtes Feature oder eine beliebige Liste von Features aktiviert werden kann, um ausgeführt werden zu können. Dazu können Sie eine FeatureGateAttribute
verwenden, die sich im Microsoft.FeatureManagement.Mvc
-Namespace befindet.
[FeatureGate("FeatureX")]
public class HomeController : Controller
{
…
}
Die HomeController
oben wird von „FeatureX“ abgegrenzt. „FeatureX“ muss aktiviert werden, bevor eine in HomeController
enthaltene Aktion ausgeführt werden kann.
[FeatureGate("FeatureX")]
public IActionResult Index()
{
return View();
}
Für die obige Index
-MVC-Aktion muss „FeatureX“ aktiviert sein, bevor sie ausgeführt werden kann.
Deaktivierte Aktionsbehandlung
Wenn ein MVC-Controller oder eine Aktion blockiert wird, da keine der von ihr definierten Features aktiviert ist, wird ein registrierter IDisabledFeaturesHandler
aufgerufen. Standardmäßig wird ein minimalistischer Handler registriert, der HTTP 404 zurückgibt. Dies kann mithilfe der IFeatureManagementBuilder
beim Registrieren von Featurekennzeichnungen überschrieben werden.
public interface IDisabledFeaturesHandler
{
Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}
Ansicht
In MVC-Ansichten können <feature>
-Kennzeichnungen verwendet werden, um Inhalte bedingt zu rendern, basierend darauf, ob ein Feature aktiviert ist oder nicht.
<feature name="FeatureX">
<p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
Sie können die Kennzeichnungshilfsauswertung auch negieren, um Inhalte anzuzeigen, wenn ein Feature oder eine Gruppe von Features deaktiviert ist. Durch Festlegen von negate="true"
im folgenden Beispiel wird der Inhalt nur gerendert, wenn FeatureX
deaktiviert ist.
<feature negate="true" name="FeatureX">
<p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
Die <feature>
-Kennzeichnung kann auf mehrere Features verweisen, indem eine durch Trennzeichen getrennte Liste von Features im name
-Attribut angegeben wird.
<feature name="FeatureX,FeatureY">
<p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
Standardmäßig müssen alle aufgelisteten Features aktiviert sein, damit die Featurekennzeichnung gerendert wird. Dieses Verhalten kann überschrieben werden, indem das requirement
-Attribut hinzugefügt wird, wie im folgenden Beispiel gezeigt.
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
In MVC-Ansichten können <feature>
-Kennzeichnungen verwendet werden, um Inhalte bedingt zu rendern, basierend darauf, ob ein Feature aktiviert ist oder ob eine bestimmte Variante eines Features zugewiesen ist. Weitere Informationen finden Sie im Abschnitt Varianten.
<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>
Sie können die Kennzeichnungshilfsauswertung auch negieren, um Inhalte anzuzeigen, wenn ein Feature oder eine Gruppe von Features deaktiviert ist. Durch Festlegen von negate="true"
im folgenden Beispiel wird der Inhalt nur gerendert, wenn FeatureX
deaktiviert ist.
<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>
Die <feature>
-Kennzeichnung kann auf mehrere Features/Varianten verweisen, indem eine durch Trennzeichen getrennte Liste von Features/Varianten im name
/variant
-Attribut angegeben wird.
<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>
Hinweis
Wenn variant
angegeben, sollte nur ein Feature angegeben werden.
Standardmäßig müssen alle aufgelisteten Features aktiviert sein, damit die Featurekennzeichnung gerendert wird. Dieses Verhalten kann überschrieben werden, indem das requirement
-Attribut hinzugefügt wird, wie im folgenden Beispiel gezeigt.
Hinweis
Wenn ein requirement
von And
in Verbindung mit variant
verwendet wird, wird ein Fehler ausgelöst, da mehrere Varianten niemals zugewiesen werden können.
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
Die <feature>
-Kennzeichnung erfordert ein Kennzeichnungshilfsprogramm. Dazu fügen Sie der Datei ViewImports.cshtml das Hilfsprogramm der Featureverwaltungskennzeichnung hinzu.
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore
MVC-Filter
MVC-Aktionsfilter können basierend auf dem Status eines Features für die bedingte Ausführung eingerichtet werden. Dazu werden MVC-Filter auf eine funktionsbewusste Weise registriert.
Die Featureverwaltungspipeline unterstützt asynchrone MVC-Aktionsfilter, die IAsyncActionFilter
implementieren.
services.AddMvc(o =>
{
o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});
Der obige Code fügt einen MVC-Filter mit dem Namen SomeMvcFilter
hinzu. Dieser Filter wird nur innerhalb der MVC-Pipeline ausgelöst, wenn „FeatureX“ aktiviert ist.
Razor Pages
MVC Razor-Seiten können erfordern, dass ein bestimmtes Feature oder eine beliebige Liste von Features aktiviert wird, um ausgeführt werden zu können. Dazu können Sie eine FeatureGateAttribute
verwenden, die sich im Microsoft.FeatureManagement.Mvc
-Namespace befindet.
[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
Der obige Code richtet eine Razor-Seite ein, damit das „FeatureX“ aktiviert werden muss. Wenn das Feature nicht aktiviert ist, generiert die Seite ein HTTP 404 (NotFound)-Ergebnis.
Bei Verwendung auf Razor-Seiten muss die FeatureGateAttribute
auf dem Seitenhandlertyp platziert werden. Sie kann nicht für einzelne Handlermethoden genutzt werden.
Anwendungserstellung
Die Featureverwaltungsbibliothek kann verwendet werden, um Anwendungszweige und Middleware hinzuzufügen, die bedingt basierend auf dem Featurestatus ausgeführt werden.
app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");
Mit dem obigen Aufruf fügt die Anwendung eine Middleware-Komponente hinzu, die nur in der Anforderungspipeline angezeigt wird, wenn das Feature „FeatureX“ aktiviert ist. Wenn das Feature während der Laufzeit aktiviert/deaktiviert ist, kann die Middleware-Pipeline dynamisch geändert werden.
Dies baut auf der allgemeineren Verzweigung der gesamten Anwendung auf der Grundlage eines Features auf.
app.UseForFeature(featureName, appBuilder =>
{
appBuilder.UseMiddleware<T>();
});
Implementieren eines Featurefilters
Das Erstellen eines Featurefilters bietet eine Möglichkeit, Features basierend auf von Ihnen definierten Kriterien zu aktivieren. Um einen Featurefilter zu implementieren, muss die IFeatureFilter
-Schnittstelle implementiert werden. IFeatureFilter
hat eine einzelne Methode mit dem Namen EvaluateAsync
. Wenn ein Feature angibt, dass es für einen Featurefilter aktiviert werden kann, wird die EvaluateAsync
-Methode aufgerufen. Wenn EvaluateAsync
true
zurückgibt, bedeutet dies, dass das Feature aktiviert werden soll.
Der folgende Codeausschnitt veranschaulicht das Hinzufügen eines benutzerdefinierten Featurefilters MyCriteriaFilter
.
services.AddFeatureManagement()
.AddFeatureFilter<MyCriteriaFilter>();
Featurefilter werden durch Aufrufen von AddFeatureFilter<T>
für die von AddFeatureManagement
zurückgegebene IFeatureManagementBuilder
registriert. Diese Featurefilter haben Zugriff auf die Dienste, die in der Dienstsammlung vorhanden sind, die zum Hinzufügen von Featurekennzeichnungen verwendet wurden. Die Abhängigkeitseinfügung kann zum Abrufen dieser Dienste verwendet werden.
Hinweis
Wenn auf Filter in Featurekennzeichnungseinstellungen verwiesen wird (z. B. appsettings.json), sollte der Filterteil des Typnamens weggelassen werden. Weitere Informationen finden Sie im Abschnitt Filter Alias Attribute
.
Parametrisierte Featurefilter
Einige Featurefilter erfordern Parameter, um zu entscheiden, ob ein Feature aktiviert werden soll oder nicht. Beispielsweise kann ein Browserfeaturefilter ein Feature für eine bestimmte Gruppe von Browsern aktivieren. Es kann gewünscht werden, dass Edge- und Chrome-Browser ein Feature aktivieren, aber nicht Firefox. Dazu kann ein Featurefilter so konzipiert werden, dass Parameter erwartet werden. Diese Parameter werden in der Featurekonfiguration angegeben, und im Code kann über den FeatureFilterEvaluationContext
-Parameter von IFeatureFilter.EvaluateAsync
zugegriffen werden.
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
hat eine Eigenschaft mit dem Namen Parameters
. Diese Parameter stellen eine unformatierte Konfiguration dar, die der Featurefilter verwenden kann, um zu entscheiden, wie das Feature aktiviert werden soll oder nicht. Um den Browserfeaturefilter als Beispiel erneut zu verwenden, könnte der Filter Parameters
verwenden, um eine Reihe zulässiger Browser zu extrahieren, die für das Feature angegeben würden - und überprüfen Sie dann, ob die Anforderung von einem dieser Browser gesendet wird.
[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
}
}
Filteralias-Attribut
Wenn ein Featurefilter für eine Featurekennzeichnung registriert ist, wird der in der Konfiguration verwendete Alias der Name des Featurefiltertyps mit dem Filtersuffix (falls vorhanden) entfernt. Beispielsweise würde MyCriteriaFilter
in der Konfiguration als MyCriteria bezeichnet.
"MyFeature": {
"EnabledFor": [
{
"Name": "MyCriteria"
}
]
}
Dies kann mithilfe von FilterAliasAttribute
überschrieben werden. Ein Featurefilter kann mit diesem Attribut versehen werden, um den Namen zu deklarieren, der in der Konfiguration verwendet werden soll, um auf diesen Featurefilter in einer Featurekennzeichnung zu verweisen.
Fehlende Featurefilter
Wenn ein Feature so konfiguriert ist, dass es für einen bestimmten Featurefilter aktiviert ist und dieser Featurefilter nicht registriert ist, wird eine Ausnahme ausgelöst, wenn das Feature ausgewertet wird. Die Ausnahme kann mithilfe der Featureverwaltungsoptionen deaktiviert werden.
services.Configure<FeatureManagementOptions>(options =>
{
options.IgnoreMissingFeatureFilters = true;
});
Verwenden von HttpContext
Featurefilter können auswerten, ob ein Feature basierend auf den Eigenschaften einer HTTP-Anforderung aktiviert werden soll. Dies wird durch Überprüfen des HTTP-Kontexts ausgeführt. Ein Featurefilter kann einen Verweis auf den HTTP-Kontext abrufen, indem eine IHttpContextAccessor
-Abhängigkeitsinjektion abgerufen wird.
public class BrowserFilter : IFeatureFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
public BrowserFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
}
Der IHttpContextAccessor
-Container zum Einfügen von Abhängigkeiten muss beim Start hinzugefügt werden, damit er verfügbar ist. Er kann mit der folgenden Methode in IServiceCollection
registriert werden.
public void ConfigureServices(IServiceCollection services)
{
…
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
…
}
Erweitert:IHttpContextAccessor
/HttpContext
sollte nicht in den Razor-Komponenten von serverseitigen Blazor-Apps verwendet werden. Der empfohlene Ansatz zum Übergeben des HTTP-Kontexts in Blazor-Apps besteht darin, die Daten in einen bereichsbezogenen Dienst zu kopieren. Bei Blazor-Apps sollte AddScopedFeatureManagement
verwendet werden, um die Featureverwaltungsdienste zu registrieren. Weitere Informationen finden Sie im Abschnitt Scoped Feature Management Services
.
Bereitstellen eines Kontexts für die Featureauswertung
In Konsolenanwendungen gibt es keinen Umgebungskontext wie HttpContext
, den Featurefilter abrufen und verwenden können, um zu überprüfen, ob ein Feature aktiviert oder deaktiviert sein soll. In diesem Fall müssen Anwendungen ein Objekt bereitstellen, das einen Kontext im Featureverwaltungssystem für die Verwendung durch Featurefilter darstellt. Zu diesem Zweck wird IFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext)
verwendet. Das appContext-Objekt, das dem Featureverwalter bereitgestellt wird, kann von Featurefiltern verwendet werden, um den Status eines Features auszuwerten.
MyAppContext context = new MyAppContext
{
AccountId = current.Id;
}
if (await featureManager.IsEnabledAsync(feature, context))
{
…
}
Kontextbezogene Featurefilter
Kontextbezogene Featurefilter implementieren die IContextualFeatureFilter<TContext>
-Schnittstelle. Diese speziellen Featurefilter können den Kontext nutzen, der beim Aufrufen von IFeatureManager.IsEnabledAsync<TContext>
übergeben wird. Der TContext
-Typparameter in IContextualFeatureFilter<TContext>
beschreibt, welchen Kontexttyp der Filter verarbeiten kann. Auf diese Weise kann der Entwickler eines Kontextfeaturefilters beschreiben, was für diejenigen erforderlich ist, die ihn nutzen möchten. Da jeder Typ ein untergeordnetes Objekt ist, kann ein Filter, der implementiert wird, für jeden bereitgestellten IContextualFeatureFilter<object>
-Kontext aufgerufen werden. Um ein Beispiel für einen spezifischeren Kontextfeaturefilter zu veranschaulichen, sollten Sie ein Feature in Betracht ziehen, das aktiviert ist, wenn sich ein Konto in einer konfigurierten Liste der aktivierten Konten befindet.
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
}
}
Wir können sehen, dass ein AccountIdFilter
-Objekt erforderlich ist, das IAccountContext
bereitstellt, um den Status eines Features auswerten zu können. Bei Verwendung dieses Featurefilters muss der Aufrufer sicherstellen, dass das übergebene Objekt IAccountContext
implementiert.
Hinweis
Nur eine einzelne Featurefilterschnittstelle kann von einem einzelnen Typ implementiert werden. Wenn Sie versuchen, einen Featurefilter hinzuzufügen, der mehr als eine einzelne Featurefilterschnittstelle implementiert, führt dies zu einer ArgumentException
.
Verwenden kontextbezogener und nicht kontextbezogener Filter mit demselben Alias
Filter von IFeatureFilter
und IContextualFeatureFilter
können denselben Alias gemeinsam nutzen. Insbesondere können Sie einen Filteralias gemeinsam mit 0 oder 1 IFeatureFilter
und 0 oder N IContextualFeatureFilter<ContextType>
haben, solange es höchstens einen anwendbaren Filter für ContextType
gibt.
In der folgenden Passage wird der Prozess der Auswahl eines Filters beschrieben, wenn kontextbezogene und nicht kontextbezogene Filter mit demselben Namen in einer Anwendung registriert sind.
Angenommen, Sie haben einen nicht kontextbezogenen Filter namens FilterA
und zwei kontextbezogene Filter FilterB
und FilterC, die TypeB
- bzw. TypeC
-Kontext akzeptieren. Alle drei Filter verwenden denselben Alias SharedFilterName
.
Außerdem verfügen Sie über eine Featurekennzeichnung MyFeature
, die den Featurefilter SharedFilterName
in seiner Konfiguration verwendet.
Wenn alle drei Filter registriert sind:
- Wenn Sie IsEnabledAsync("MyFeature") aufrufen, wird die
FilterA
-Funktion zum Auswerten der Featurekennzeichnungen verwendet. - Wenn Sie IsEnabledAsync("MyFeature", context) aufrufen, wird
FilterB
verwendet, wenn der Typ des KontextsTypeB
ist. Wenn der KontexttypTypeC
ist, wirdFilterC
verwendet. - Wenn Sie IsEnabledAsync("MyFeature", context) aufrufen, wird
FilterA
verwendet, wenn der Typ des KontextsTypeF
ist.
Integrierte Featurefilter
Es gibt einige Featurefilter, die im Microsoft.FeatureManagement
-Paket enthalten sind: PercentageFilter
, TimeWindowFilter
, ContextualTargetingFilter
und TargetingFilter
. Alle Filter, mit Ausnahme von TargetingFilter
werden automatisch hinzugefügt, wenn die Featureverwaltung durch die AddFeatureManagement
-Methode registriert wird. Die TargetingFilter
-Methode wird mit der WithTargeting
-Methode hinzugefügt, die im folgenden Targeting
-Abschnitt beschrieben ist.
Jeder der integrierten Featurefilter verfügt über eigene Parameter. Hier ist die Liste der Featurefilter zusammen mit Beispielen.
Microsoft.Percentage
Dieser Filter bietet die Möglichkeit, ein Feature basierend auf einem festgelegten Prozentsatz zu aktivieren.
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.Percentage",
"Parameters": {
"Value": 50
}
}
]
}
Microsoft.TimeWindow
Dieser Filter bietet die Möglichkeit, ein Feature basierend auf einem Zeitfenster zu aktivieren. Wenn nur End
angegeben ist, wird das Feature bis zu diesem Zeitpunkt aktiviert. Wenn nur Start
angegeben ist, wird das Feature zu allen Zeitpunkten berücksichtigt.
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.TimeWindow",
"Parameters": {
"Start": "Wed, 01 May 2019 13:59:59 GMT",
"End": "Mon, 01 Jul 2019 00:00:00 GMT"
}
}
]
}
Das Zeitfenster kann so konfiguriert werden, dass es regelmäßig wieder auftritt. Dies kann für Szenarien nützlich sein, in denen ein Feature möglicherweise während eines niedrigen oder hohen Datenverkehrszeitraums eines Tages oder bestimmter Wochentage aktiviert werden muss. Um das einzelne Zeitfenster auf wiederkehrende Zeitfenster zu erweitern, sollte die Serienregel im Recurrence
-Parameter angegeben werden.
Hinweis
Start
und End
müssen beide zum Aktivieren von Recurrence
angegeben werden.
"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"
}
}
}
}
]
}
Die Recurrence
-Einstellungen bestehen aus zwei Teilen: Pattern
(wie oft das Zeitfenster wiederholt wird) und Range
(wie lange das Serienmuster wiederholt wird).
Serienmuster
Es gibt zwei mögliche Serienmustertypen: Daily
und Weekly
. Beispielsweise könnte ein Zeitfenster „jeden Tag“, „alle drei Tage“, „jeden Montag“ oder „jeden anderen Freitag“ wiederholen.
Je nach Typ sind bestimmte Felder der Pattern
erforderlich, optional oder werden ignoriert.
Daily
Das tägliche Serienmuster bewirkt, dass das Zeitfenster basierend auf einer Anzahl von Tagen zwischen jeder Ausführung wiederholt wird.
Eigenschaft Relevance Beschreibung Typ Erforderlich Muss auf Daily
festgelegt sein.Intervall Optional Gibt die Anzahl der Tage zwischen jeder Ausführung an. Der Standardwert ist 1. Weekly
Das wöchentliche Serienmuster bewirkt, dass das Zeitfenster am selben Tag oder an Tagen der Woche basierend auf der Anzahl der Wochen zwischen den einzelnen Ausführungen wiederholt wird.
Eigenschaft Relevance Beschreibung Typ Erforderlich Muss auf Weekly
festgelegt sein.DaysOfWeek Erforderlich Gibt an, an welchen Wochentagen das Ereignis eintritt. Intervall Optional Gibt die Anzahl der Wochen zwischen den einzelnen Ausführungen an. Der Standardwert ist 1. FirstDayOfWeek Optional Gibt an, welcher Tag als erster Tag der Woche gilt. Der Standardwert ist Sunday
.Im folgenden Beispiel wird das Zeitfenster jeden zweiten Montag und Dienstag wiederholt
"Pattern": { "Type": "Weekly", "Interval": 2, "DaysOfWeek": ["Monday", "Tuesday"] }
Hinweis
Start
muss eine gültige erste Ausführung sein, die zum Serienmuster passt. Darüber hinaus kann die Dauer des Zeitfensters nicht länger sein als die Anzahl der Ausführungen. Beispielsweise ist es ungültig, dass täglich ein 25-Stunden-Zeitfenster wieder auftritt.
Serienbereich
Es gibt drei mögliche Serienbereichstypen: NoEnd
, EndDate
und Numbered
.
NoEnd
Der
NoEnd
-Bereich bewirkt, dass die Serie unbegrenzt auftritt.Eigenschaft Relevance Beschreibung Typ Erforderlich Muss auf NoEnd
festgelegt sein.EndDate
Der
EndDate
-Bereich bewirkt, dass das Zeitfenster an allen Tagen auftritt, die dem entsprechenden Muster bis zum Enddatum entsprechen.Eigenschaft Relevance Beschreibung Typ Erforderlich Muss auf EndDate
festgelegt sein.EndDate Erforderlich Gibt das Datum an, zu dem das Anwenden des Musters beendet werden soll. Solange die Startzeit der letzten Ausführung vor dem Enddatum liegt, darf die Endzeit dieser Ausführung darüber hinaus gehen. Im folgenden Beispiel wird das Zeitfenster jeden Tag wiederholt, bis die letzte Ausführung am 1. April 2024 erfolgt.
"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
Der
Numbered
-Bereich bewirkt, dass das Zeitfenster eine feste Anzahl von Malen (basierend auf dem Muster) auftritt.Eigenschaft Relevance Beschreibung Typ Erforderlich Muss auf Numbered
festgelegt sein.NumberOfOccurrences Erforderlich Gibt die Anzahl der Ausführungen an. Im folgenden Beispiel wird das Zeitfenster montags und dienstags wiederholt, bis es drei Ausführungen gibt, die jeweils am 1. April (Mo), 2. April (Di) und 8.April (Mo) auftreten.
"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 } }
Um eine Serienregel zu erstellen, müssen Sie sowohl Pattern
als auch Range
angeben. Jeder Mustertyp kann mit jedem Bereichstyp verwendet werden.
Erweitert: Der Zeitzonenoffset der Start
-Eigenschaft wird auf die Serieneinstellungen angewendet.
Microsoft.Targeting
Dieser Filter bietet die Möglichkeit, ein Feature für eine Zielgruppe zu aktivieren. Eine ausführliche Erläuterung der Zielbestimmung wird im folgenden Abschnitt zur Zielbestimmung erläutert. Die Filterparameter enthalten ein Audience
-Objekt, das Benutzer, Gruppen, ausgeschlossene Benutzer/Gruppen und einen Standardprozentsatz der Benutzerbasis beschreibt, die Zugriff auf das Feature haben sollen. Jedes Gruppenobjekt, das im Groups
-Abschnitt aufgeführt ist, muss auch angeben, welcher Prozentsatz der Mitglieder der Gruppe Zugriff haben soll. Wenn ein Benutzer im Exclusion
-Abschnitt angegeben wird, entweder direkt oder wenn sich der Benutzer in einer ausgeschlossenen Gruppe befindet, ist das Feature deaktiviert. Andernfalls, wenn ein Benutzer direkt im Users
-Abschnitt angegeben wird, oder wenn der Benutzer den Prozentsatz einer der Gruppenrollouts enthält, oder wenn der Benutzer in den Standardrollout-Prozentsatz fällt, wird dieses Feature aktiviert.
"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"
]
}
}
}
}
]
}
Aliasnamespaces für Featurefilter
Alle integrierten Featurefilteralias befinden sich im Microsoft
-Featurefilternamespace. Dies geschieht, um Konflikten mit anderen Featurefiltern, die denselben Alias verwenden können, zu verhindern. Die Segmente eines Featurefilternamespaces werden durch das Zeichen „.“ geteilt. Auf einen Featurefilter kann durch seinen vollqualifizierten Alias wie Microsoft.Percentage
oder durch das letzte Segment verwiesen werden, das im Fall von Microsoft.Percentage
Percentage
ist.
Zielbestimmung
Die Zielbestimmung ist eine Featureverwaltungsstrategie, mit der Entwickler neue Features schrittweise für ihre Benutzerbasis bereitstellen können. Die Strategie basiert auf dem Konzept der Zielgruppenadressierung einer Gruppe von Benutzern, die als Zielgruppe bezeichnet werden. Eine Benutzergruppe besteht aus bestimmten Benutzern, Gruppen, ausgeschlossenen Benutzern/Gruppen und einem bestimmten Prozentsatz der gesamten Benutzerbasis. Die Gruppen, die in der Zielgruppe enthalten sind, können weiter in Prozentsätze ihrer Gesamtmitglieder unterteilt werden.
Die folgenden Schritte veranschaulichen ein Beispiel für ein progressives Rollout für ein neues Feature „Beta“:
- Individuelle Benutzer Jeff und Alicia erhalten Zugriff auf die Betaversion
- Ein anderer Benutzer, Mark, fordert die Anmeldung an und wird aufgenommen.
- Zwanzig Prozent einer Gruppe, die als „Ring1“-Benutzer bezeichnet wird, sind in der Betaversion enthalten.
- Die Anzahl der in der Betaversion enthaltenen „Ring1“-Benutzer wird auf 100 Prozent erhöht.
- Fünf Prozent der Benutzerbasis sind in der Betaversion enthalten.
- Der Rollout-Prozentsatz wird auf 100 Prozent erhöht, und das Feature wird vollständig eingeführt.
Diese Strategie für das Rollout eines Features ist über den enthaltenen Microsoft.Targeting-Featurefilter in die Bibliothek integriert.
Zielbestimmung in einer Webanwendung
Eine Beispielwebanwendung, die den Zielfeaturefilter verwendet, ist im FeatureFlagDemo-Beispielprojekt verfügbar.
Um mit der Verwendung von TargetingFilter
einer Anwendung zu beginnen, muss sie der Dienstsammlung der Anwendung genauso wie jeder andere Featurefilter hinzugefügt werden. Im Gegensatz zu anderen integrierten Filtern basiert die TargetingFilter
auf einem anderen Dienst, welcher der Dienstauflistung der Anwendung hinzugefügt werden soll. Dieser Dienst ist ein ITargetingContextAccessor
.
Microsoft.FeatureManagement.AspNetCore
stellt eine Standardimplementierung von ITargetingContextAccessor
bereit, wodurch Zielinformationen aus dem HttpContext
einer Anforderung extrahiert werden. Sie können den standardmäßigen Zielkontext-Accessor verwenden, wenn Sie die Zielbestimmung einrichten, indem Sie die nicht generische Überladung WithTargeting
auf dem IFeatureManagementBuilder
verwenden.
Der standardmäßige Zielkontext-Accessor und TargetingFilter
werden durch Aufrufen von WithTargeting
auf dem IFeatureManagementBuilder
registriert.
services.AddFeatureManagement()
.WithTargeting();
Sie können auch eine benutzerdefinierte Implementierung für ITargetingContextAccessor
und TargetingFilter
durch Aufrufen von WithTargeting<T>
registrieren. Nachfolgend finden Sie ein Beispiel zum Einrichten der Featureverwaltung in einer Webanwendung, um die TargetingFilter
mit einer Implementierung von ITargetingContextAccessor
namens ExampleTargetingContextAccessor
zu verwenden.
services.AddFeatureManagement()
.WithTargeting<ExampleTargetingContextAccessor>();
ITargetingContextAccessor
Um TargetingFilter
in einer Webanwendung zu verwenden, ist eine Implementierung von ITargetingContextAccessor
erforderlich. Dies liegt daran, dass bei der Ausführung einer Zielauswertung kontextbezogene Informationen benötigt werden, wie z. B. welcher Benutzer derzeit ausgewertet wird. Diese Informationen werden als die TargetingContext
bezeichnet. Verschiedene Anwendungen können diese Informationen von verschiedenen Stellen extrahieren. Einige häufige Beispiele dafür, wo eine Anwendung den Zielkontext abrufen kann, sind der HTTP-Kontext der Anforderung oder eine Datenbank.
Ein Beispiel zum Extrahieren von Zielkontextinformationen aus dem HTTP-Kontext der Anwendung ist der DefaultHttpTargetingContextAccessor
, der vom Microsoft.FeatureManagement.AspNetCore
-Paket bereitgestellt wird. Er wird Zielinformationen aus HttpContext.User
extrahieren. UserId
-Informationen werden aus dem Identity.Name
-Feld extrahiert werden, und Groups
-Informationen werden aus Ansprüchen des Typs Role
extrahiert werden. Diese Implementierung basiert auf der Verwendung von IHttpContextAccessor
, die hier erläutert wird.
Zielbestimmung in einer Konsolenanwendung
Der Zielfilter basiert auf einem Zielkontext, um zu bewerten, ob ein Feature aktiviert werden soll. Dieser Zielkontext enthält Informationen, z. B. den aktuell ausgewerteten Benutzer und welche Gruppen der Benutzer enthält. In Konsolenanwendungen steht in der Regel kein Umgebungskontext zur Verfügung, um diese Informationen in den Zielfilter zu übertragen, daher muss er direkt übergeben werden, wenn FeatureManager.IsEnabledAsync
aufgerufen wird. Dies wird mithilfe der ContextualTargetingFilter
unterstützt. Anwendungen, die den Zielkontext im Featureverwalter freigeben müssen, sollten dies anstelle der TargetingFilter.
verwenden.
Da ContextualTargetingFilter
eine IContextualTargetingFilter<ITargetingContext>
ist, muss eine Implementierung von ITargetingContext
an IFeatureManager.IsEnabledAsync
übergeben werden, damit sie ein Feature auswerten und aktivieren kann.
IFeatureManager fm;
…
// userId and groups defined somewhere earlier in application
TargetingContext targetingContext = new TargetingContext
{
UserId = userId,
Groups = groups
};
await fm.IsEnabledAsync(featureName, targetingContext);
Der ContextualTargetingFilter
verwendet weiterhin den Featurefilteralias Microsoft.Targeting, sodass die Konfiguration für diesen Filter mit dem in diesem Abschnitt erwähnten entspricht.
Ein Beispiel, das die ContextualTargetingFilter
in einer Konsolenanwendung verwendet, ist im Beispielprojekt TargetingConsoleApp verfügbar.
Optionen für die Zielauswertung
Optionen stehen zur Verfügung, um anzupassen, wie die Zielauswertung für alle Features ausgeführt wird. Diese Optionen können beim Einrichten der Featureverwaltung konfiguriert werden.
services.Configure<TargetingEvaluationOptions>(options =>
{
options.IgnoreCase = true;
});
Zielausschluss
Beim Definieren einer Benutzergruppe können Benutzer und Gruppen von der Zielgruppe ausgeschlossen werden. Dies ist nützlich, wenn ein Feature für eine Gruppe von Benutzern eingeführt wird, aber einige Benutzer oder Gruppen aus dem Rollout ausgeschlossen werden müssen. Der Ausschluss wird durch Hinzufügen einer Liste von Benutzern und Gruppen zur Exclusion
-Eigenschaft der Benutzergruppe definiert.
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0
"Exclusion": {
"Users": [
"Mark"
]
}
}
Im obigen Beispiel ist das Feature für Benutzer mit dem Namen Jeff
und Alicia
aktiviert. Es ist auch für Benutzer in der Gruppe mit dem Namen Ring0
aktiviert. Wenn der Benutzer jedoch Mark
benannt ist, ist das Feature deaktiviert, unabhängig davon, ob er sich in der Gruppe Ring0
befindet oder nicht. Ausschlüsse haben Vorrang vor dem Rest des Zielfilters.
Varianten
Wenn einer Anwendung neue Features hinzugefügt werden, kann es vorkommen, dass ein Feature über mehrere verschiedene vorgeschlagene Entwurfsoptionen verfügt. Eine gängige Lösung für die Entscheidung für ein Design ist eine Form von A/B-Tests, die beinhaltet, eine andere Version des Features für verschiedene Segmente der Benutzerbasis bereitzustellen und eine Version basierend auf der Benutzerinteraktion auszuwählen. In dieser Bibliothek wird diese Funktionalität aktiviert, indem verschiedene Konfigurationen eines Features mit Varianten dargestellt werden.
Varianten aktivieren eine Featurekennzeichnung, um mehr als eine einfache Ein-/Aus-Kennzeichnung zu werden. Eine Variante stellt einen Wert einer Featurekennzeichnung dar, die eine Zeichenfolge, eine Zahl, ein boolescher Wert oder sogar ein Konfigurationsobjekt sein kann. Eine Featurekennzeichnung, die Varianten deklariert, sollte definieren, unter welchen Umständen jede Variante verwendet werden soll, was im Abschnitt Allocating Variants ausführlicher behandelt wird.
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; }
}
Abrufen von Varianten
Für jedes Feature kann eine Variante mithilfe der GetVariantAsync
-Methode von IVariantFeatureManager
abgerufen werden.
…
IVariantFeatureManager featureManager;
…
Variant variant = await featureManager.GetVariantAsync(MyFeatureFlags.FeatureU, CancellationToken.None);
IConfigurationSection variantConfiguration = variant.Configuration;
// Do something with the resulting variant and its configuration
Sobald eine Variante abgerufen wird, kann die Konfiguration einer Variante direkt als IConfigurationSection
-Eigenschaft der Variante Configuration
verwendet werden. Eine weitere Option besteht darin, die Konfiguration mithilfe des .NET-Konfigurationsbindungsmuster an ein Objekt zu binden.
IConfigurationSection variantConfiguration = variant.Configuration;
MyFeatureSettings settings = new MyFeatureSettings();
variantConfiguration.Bind(settings);
Die zurückgegebene Variante hängt vom aktuell ausgewerteten Benutzer ab, und diese Informationen werden aus einer Instanz von TargetingContext
abgerufen. Dieser Kontext kann entweder beim Aufrufen von GetVariantAsync
übergeben werden, oder er kann automatisch aus einer Implementierung von ITargetingContextAccessor
abgerufen werden, wenn eine registriert ist.
Variant Feature Flag-Deklaration
Im Vergleich zu normalen Featurekennzeichnungen weisen Variantenfeature-Flags zwei zusätzliche Eigenschaften auf: variants
und allocation
. Die variants
-Eigenschaft ist ein Array, das die für dieses Feature definierten Varianten enthält. Die allocation
-Eigenschaft definiert, wie diese Varianten für das Feature zugewiesen werden sollen. Genau wie beim Deklarieren normaler Featurekennzeichnungen können Sie Variantenfeaturekennzeichnung in einer JSON-Datei einrichten. Hier sehen Sie ein Beispiel für ein Variantenfeaturekennzeichnung.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"default_when_enabled": "Small",
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
]
},
"variants": [
{
"name": "Big"
},
{
"name": "Small"
}
]
}
]
}
}
Definieren von Varianten
Jede Variante verfügt über zwei Eigenschaften: einen Namen und eine Konfiguration. Der Name wird verwendet, um auf eine bestimmte Variante zu verweisen, und die Konfiguration ist der Wert dieser Variante. Die Konfiguration kann mithilfe der Eigenschaft configuration_value
festgelegt werden. configuration_value
ist eine Inlinekonfiguration, die ein Zeichenfolgen-, Zahlen-, boolesches oder Konfigurationsobjekt sein kann. Wenn configuration_value
nicht angegeben wird, ist die Eigenschaft Configuration
der zurückgegebenen Variante null.
Für jedes Feature unter der variants
-Eigenschaft wird eine Liste aller möglichen Varianten definiert.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"variants": [
{
"name": "Big",
"configuration_value": {
"Size": 500
}
},
{
"name": "Small",
"configuration_value": {
"Size": 300
}
}
]
}
]
}
}
Zuweisung von Varianten
Der Prozess der Zuordnung der Varianten eines Features wird durch die allocation
-Eigenschaft des Features bestimmt.
"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"
}
]
Die allocation
-Einstellung eines Features weist die folgenden Eigenschaften auf:
Eigenschaft | Beschreibung |
---|---|
default_when_disabled |
Gibt an, welche Variante verwendet werden soll, wenn eine Variante angefordert wird, während das Feature als deaktiviert gilt. |
default_when_enabled |
Gibt an, welche Variante verwendet werden soll, wenn eine Variante angefordert wird, während das Feature als aktiviert gilt und dem Benutzer keine andere Variante zugewiesen wurde. |
user |
Gibt eine Variante und eine Liste von Benutzern an, denen diese Variante zugewiesen werden soll. |
group |
Gibt eine Variante und eine Liste von Gruppen an. Die Variante wird zugewiesen, wenn sich der Benutzer in mindestens einer der Gruppen befindet. |
percentile |
Gibt eine Variante und einen Prozentbereich an, in den der berechnete Prozentsatz des Benutzers passt, damit diese Variante zugewiesen werden soll. |
seed |
Der Wert, auf dem prozentuale Berechnungen für percentile basieren. Die prozentuale Berechnung für einen bestimmten Benutzer ist für alle Features gleich, wenn derselbe seed -Wert verwendet wird. Wenn kein seed angegeben wird, wird basierend auf dem Featurenamen ein Standardnamenswert erstellt. |
Wenn das Feature im obigen Beispiel nicht aktiviert ist, weist der Featureverwalter dem aktuellen Benutzer die als default_when_disabled
markierte Variante zu, die in diesem Fall Small
ist.
Wenn das Feature aktiviert ist, überprüft der Featureverwalter die Zuweisungen user
, group
und percentile
, um eine Variante zuzuweisen. Wenn der ausgewertete Benutzer in der Gruppe mit dem Namen Ring1
Marsha
benannt wird oder der Benutzer zwischen das Quantil 0 und 10 fällt, wird dem Benutzer die angegebene Variante zugewiesen. In diesem Fall würden all diese Werte die Big
-Variante zurückgeben. Wenn keine dieser Zuordnungen übereinstimmt, wird dem Benutzer die default_when_enabled
-Variante zugewiesen, die Small
ist.
Die Zuordnungslogik ähnelt dem Microsoft.Targeting-Featurefilter, aber es gibt einige Parameter, die in der Zielbestimmung vorhanden sind, die nicht in der Zuordnung enthalten sind, und umgekehrt. Die Ziel- und Zuordnungsergebnisse hängen nicht zusammen.
Hinweis
Um die Zuordnung von Featurevarianten zu ermöglichen, müssen Sie ITargetingContextAccessor
registrieren. Dies kann durch Aufrufen der WithTargeting<T>
-Methode erfolgen.
Überschreiben des aktivierten Zustands mit einem Variantenwert
Sie können Varianten verwenden, um den aktivierten Status einer Featurekennzeichnung außer Kraft zu setzen. Dies bietet Varianten die Möglichkeit, die Auswertung einer Featurekennzeichnung zu erweitern. Wenn IsEnabled
bei einem Flag mit Varianten aufgerufen wird, überprüft der Featureverwalter, ob die dem aktuellen Benutzer zugewiesene Variante so konfiguriert ist, dass sie das Ergebnis überschreibt. Dies erfolgt mithilfe der optionalen Varianteneigenschaft status_override
. Diese Eigenschaft ist standardmäßig auf None
festgelegt, was bedeutet, dass die Variante keine Auswirkungen darauf hat, ob die Kennzeichnung als aktiviert oder deaktiviert gilt. Wenn Sie status_override
auf Enabled
festlegen, kann die Variante bei Auswahl eine zu aktivierende Kennzeichnung außer Kraft setzen. Das Festlegen von status_override
auf Disabled
bietet die entgegengesetzte Funktionalität, wodurch die Kennzeichnung deaktiviert wird, wenn die Variante ausgewählt wird. Ein Feature mit einem enabled
-Status von false
kann nicht außer Kraft gesetzt werden.
Wenn Sie eine Featurekennzeichnung mit binären Varianten verwenden, kann die status_override
-Eigenschaft sehr hilfreich sein. Sie können APIs wie IsEnabledAsync
und FeatureGateAttribute
in Ihrer Anwendung weiterhin verwenden, während Sie von den neuen Features profitieren, die mit Varianten enthalten sind, z. B. Quantilzuweisung und 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"
}
]
}
Im obigen Beispiel ist das Feature immer aktiviert. Wenn sich der aktuelle Benutzer im berechneten Quantilbereich von 10 bis 20 befindet, wird die On
-Variante zurückgegeben. Andernfalls wird die Off
-Variante zurückgegeben und da status_override
gleich Disabled
ist, wird das Feature jetzt als deaktiviert betrachtet.
Varianten in Abhängigkeitsinjektion
Variantenfeaturekennzeichnungen können in Verbindung mit Abhängigkeitsinjektion verwendet werden, um unterschiedliche Implementierungen eines Diensts für verschiedene Benutzer anzuzeigen. Dies wird mithilfe der IVariantServiceProvider<TService>
-Schnittstelle erreicht.
IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...
IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken);
Im obigen Codeausschnitt ruft die IVariantServiceProvider<IAlgorithm>
eine Implementierung von IAlgorithm
aus dem Container zum Einfügen von Abhängigkeiten ab. Die gewählte Implementierung ist abhängig von:
- Der Featurekennzeichnung, bei welcher der
IAlgorithm
-Dienst registriert wurde. - Die zugewiesene Variante für dieses Feature.
-Die IVariantServiceProvider<T>
Anwendung wird durch Aufrufen von IFeatureManagementBuilder.WithVariantService<T>(string featureName)
zur Verfügung gestellt. Ein Beispiel finden Sie weiter unten.
services.AddFeatureManagement()
.WithVariantService<IAlgorithm>("ForecastAlgorithm");
Der obige Aufruf stellt IVariantServiceProvider<IAlgorithm>
in der Dienstsammlung zur Verfügung. Implementierungen von IAlgorithm
müssen separat über eine Add-Methode wie z. B. services.AddSingleton<IAlgorithm, SomeImplementation>()
hinzugefügt werden. Die Implementierung von IAlgorithm
, die vom IVariantServiceProvider
verwendet wird, hängt von der Variantenfeaturekennzeichnung ForecastAlgorithm
ab. Wenn der Dienstauflistung keine Implementierung von IAlgorithm
hinzugefügt wird, gibt die IVariantServiceProvider<IAlgorithm>.GetServiceAsync()
eine Aufgabe mit einem NULL-Ergebnis zurück.
{
// The example variant feature flag
"id": "ForecastAlgorithm",
"enabled": true,
"variants": [
{
"Name": "AlgorithmBeta"
},
...
]
}
Variant Services Alias-Attribut
[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
...
}
Der Variantendienstanbieter verwendet die Typnamen von Implementierungen, um der zugeordneten Variante zu entsprechen. Wenn ein Variantendienst mit VariantServiceAliasAttribute
versehen ist, sollte der in diesem Attribut deklarierte Name in der Konfiguration verwendet werden, um auf diesen Variantendienst zu verweisen.
Telemetrie
Wenn eine Featurekennzeichnungsänderung bereitgestellt wird, ist es häufig wichtig, ihre Auswirkungen auf eine Anwendung zu analysieren. Hier sind beispielsweise einige Fragen, die auftauchen können:
- Sind meine Kennzeichnungen wie erwartet aktiviert/deaktiviert?
- Erhalten bestimmte Benutzer den Zugriff auf ein bestimmtes Feature wie erwartet?
- Welche Variante sieht ein bestimmter Benutzer?
Diese Fragen können durch die Emission und Analyse von Auswertungsereignissen von Featurekennzeichnungen beantwortet werden. Diese Bibliothek verwendet die System.Diagnostics.Activity
-API, um während der Auswertung des Featureflags Ablaufverfolgungstelemetriedaten zu erzeugen.
Aktivieren der Telemetrie
Standardmäßig werden keine Telemetriekennzeichnungen ausgegeben. Um Telemetrie für eine bestimmte Featurekennzeichnung zu veröffentlichen, muss die Kennzeichnung deklarieren, dass sie für die Telemetrieemission aktiviert ist.
Bei Featurekennzeichnungen, die in appsettings.json
definiert sind, erfolgt dies mithilfe der telemetry
-Eigenschaft.
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
Der obige Appsettings-Codeausschnitt definiert eine Featurekennzeichnung namens MyFeatureFlag
, die für Telemetrie aktiviert ist. Dies wird durch das telemetry
-Objekt angegeben, das enabled
auf „true“ festlegt. Der Wert der enabled
-Eigenschaft muss true
sein, um Telemetrie für die Kennzeichnung zu veröffentlichen.
Der telemetry
-Abschnitt einer Featurekennzeichnung weist die folgenden Eigenschaften auf:
Eigenschaft | Beschreibung |
---|---|
enabled |
Gibt an, ob Telemetrie für die Featurekennzeichnung veröffentlicht werden soll. |
metadata |
Eine Sammlung von Schlüsselwertpaaren, die als Wörterbuch modelliert werden, die verwendet werden können, um benutzerdefinierte Metadaten zur Featurekennzeichnung an Auswertungsereignisse anzufügen. |
Benutzerdefinierter Telemetriedatenherausgeber
Der Featuremanager hat seine eigene ActivitySource
mit Namen „Microsoft.FeatureManagement“. Wenn telemetry
für ein Featureflag aktiviert ist, wird der Featuremanager bei jedem Starten der Auswertung des Featureflags eine Activity
starten. Wenn die Auswertung des Featureflags abgeschlossen ist, fügt der Featuremanager der aktuellen Aktivität einen ActivityEvent
mit Namen FeatureFlag
hinzu. Das FeatureFlag
-Ereignis enthält Tags, die die Informationen zur Featurekennzeichnungsauswertung enthalten, und zwar nach den im Schema FeatureEvaluationEvent definierten Feldern.
Hinweis
Alle Schlüssel-Wert-Paare, die in telemetry.metadata
des Featureflags angegeben sind, werden ebenfalls in die Tags einbezogen.
Zum Aktivieren der benutzerdefinierten Telemetriedatenveröffentlichung können Sie einen ActivityListener
erstellen und auf der Aktivitätsquelle Microsoft.FeatureManagement
lauschen. Hier ist ein Beispiel, das zeigt, wie Sie die Aktivitätsquelle der Featureverwaltung überwachen und einen Rückruf hinzufügen, wenn ein Feature ausgewertet wird.
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.
}
}
});
Weitere Informationen finden Sie unter Sammeln einer verteilten Ablaufverfolgung.
Application Insights Telemetry-Herausgeber
Das Microsoft.FeatureManagement.Telemetry.ApplicationInsights
-Paket bietet einen integrierten Telemetriedatenherausgeber, der Auswertungsdaten des Featureflags an Application Insights sendet. Um dies zu nutzen, fügen Sie einen Verweis auf das Paket hinzu, und registrieren Sie den Telemetrieherausgeber von Application Insights wie unten dargestellt.
builder.services
.AddFeatureManagement()
.AddApplicationInsightsTelemetryPublisher();
Das Microsoft.FeatureManagement.Telemetry.ApplicationInsights
-Paket stellt einen Initialisierer für Telemetriedaten bereit, mit dem automatisch alle Ereignisse mit TargetingId
gekennzeichnet werden, sodass Ereignisse mit Flagauswertungen verknüpft werden können. Um den Initialisierer für Telemetriedaten, TargetingTelemetryInitializer
, zu verwenden, fügen Sie ihn der Dienstsammlung der Anwendung hinzu.
builder.Services.AddSingleton<ITelemetryInitializer, TargetingTelemetryInitializer>();
Hinweis
Um sicherzustellen, dass TargetingTelemetryInitializer
wie erwartet funktioniert, sollte die unten beschriebene TargetingHttpContextMiddleware
verwendet werden.
Um die Persistenz des Zielkontexts in der aktuellen Aktivität zu aktivieren, können Sie die TargetingHttpContextMiddleware
verwenden.
app.UseMiddleware<TargetingHttpContextMiddleware>();
Ein Beispiel für die Verwendung finden Sie unter VariantAndTelemetryDemo.
Voraussetzungen
Dieser Telemetriedatenanbieter hängt davon ab, ob Application Insights bereits eingerichtet und als Anwendungsdienst registriert ist. Dies geschieht beispielsweise hier in der Beispielanwendung.
Dieser Telemetrieherausgeber hängt davon ab, dass Application Insights bereits eingerichtet und als Anwendungsdienst registriert ist.
Caching
Der Featurestatus wird vom IConfiguration
-System bereitgestellt. Es wird erwartet, dass zwischengespeicherte und dynamische Aktualisierungen von Konfigurationsanbietern verarbeitet werden. Der Featureverwalter fragt IConfiguration
nach dem neuesten Wert des Status eines Features, wenn ein Feature aktiviert wird.
Snapshot
Es gibt Szenarien, in denen der Status eines Features während der Lebensdauer einer Anforderung konsistent bleibt. Die von der Standard-IFeatureManager
zurückgegebenen Werte können sich ändern, wenn die IConfiguration
-Quelle, aus der sie stammt, während der Anforderung aktualisiert wird. Dies kann mithilfe von IFeatureManagerSnapshot
verhindert werden. IFeatureManagerSnapshot
kann auf die gleiche Weise wie IFeatureManager
abgerufen werden. IFeatureManagerSnapshot
implementiert die Schnittstelle von IFeatureManager
, speichert aber den ersten ausgewerteten Zustand eines Features während einer Anforderung zwischen und gibt denselben Status eines Features während seiner Lebensdauer zurück.
Benutzerdefinierte Featureanbieter
Durch die Implementierung eines benutzerdefinierten Featureanbieters können Entwickler Featurekennzeichnungen aus Quellen wie einer Datenbank oder einem Featureverwaltungsdienst abrufen. Der enthaltene Featureanbieter, der standardmäßig verwendet wird, ruft Featurekennzeichnungen aus dem Konfigurationssystem von .NET Core ab. Dadurch können Features in einer appsettings.json-Datei oder in Konfigurationsanbietern wie Azure App Configuration definiert werden. Dieses Verhalten kann ersetzt werden, um vollständige Kontrolle darüber bereitzustellen, wo Featuredefinitionen gelesen werden.
Um das Laden von Featuredefinitionen anzupassen, muss die IFeatureDefinitionProvider
-Schnittstelle implementiert werden.
public interface IFeatureDefinitionProvider
{
Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);
IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}
Um eine Implementierung von IFeatureDefinitionProvider
zu verwenden, muss es der Dienstsammlung hinzugefügt werden, bevor Sie die Featureverwaltung hinzufügen. Im folgenden Beispiel wird eine Implementierung von IFeatureDefinitionProvider
namens InMemoryFeatureDefinitionProvider
hinzugefügt.
services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
.AddFeatureManagement()
Nächste Schritte
Fahren Sie mit den folgenden Schnellstarts fort, um zu erfahren, wie Featureflags in Ihren Anwendungen verwendet werden.
Wenn Sie mehr über die Verwendung von Featurefiltern erfahren möchten, fahren Sie mit den folgenden Tutorials fort.