Teilen über


.NET-Featureverwaltung

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore

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

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
  • 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 schemadeklariert. 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 in der Konfiguration eine mit Microsoft Feature Management schema geschriebene Featurekennzeichnung gefunden werden kann, werden alle mit .NET feature management schema geschriebenen Featurekennzeichnungen ignoriert.

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 Kontexts TypeB ist. Wenn der Kontexttyp TypeC ist, wird FilterC verwendet.
  • Wenn Sie IsEnabledAsync("MyFeature", context) aufrufen, wird FilterA verwendet, wenn der Typ des Kontexts TypeF 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“:

  1. Individuelle Benutzer Jeff und Alicia erhalten Zugriff auf die Betaversion
  2. Ein anderer Benutzer, Mark, fordert die Anmeldung an und wird aufgenommen.
  3. Zwanzig Prozent einer Gruppe, die als „Ring1“-Benutzer bezeichnet wird, sind in der Betaversion enthalten.
  4. Die Anzahl der in der Betaversion enthaltenen „Ring1“-Benutzer wird auf 100 Prozent erhöht.
  5. Fünf Prozent der Benutzerbasis sind in der Betaversion enthalten.
  6. 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.

Der für den ITargetingContextAccessor-Dienst verwendete Implementierungstyp muss von der Anwendung implementiert werden, die den Zielfilter verwendet. Nachfolgend finden Sie ein Beispiel zum Einrichten der Featureverwaltung in einer Webanwendung, um die TargetingFilter mit einer Implementierung von ITargetingContextAccessor namens HttpContextTargetingContextAccessor zu verwenden.

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

Der Zielkontextaccessor und TargetingFilter werden durch Aufrufen von WithTargeting<T> auf IFeatureManagementBuilder registriert.

ITargetingContextAccessor

Um TargetingFilter in einer Webanwendung zu verwenden, ist eine Implementierung von ITargetingContextAccessor erforderlich. Dies liegt daran, dass bei der Ausführung einer Zielauswertung Informationen, wie z. B. der aktuell ausgewertete Benutzer, benötigt werden. Diese Informationen werden als Zielkontext bezeichnet. Unterschiedliche Webanwendungen 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, das die Zielkontextinformationen aus dem HTTP-Kontext der Anwendung extrahiert, ist im FeatureFlagDemo-Beispielprojekt enthalten. Diese Methode 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 entweder mithilfe den Eigenschaften configuration_reference oder configuration_value festgelegt werden. configuration_reference ist ein Zeichenfolgenpfad, der auf einen Abschnitt der aktuellen Konfiguration verweist, der die Featurekennzeichnungsdeklaration enthält. configuration_value ist eine Inlinekonfiguration, die ein Zeichenfolgen-, Zahlen-, boolesches oder Konfigurationsobjekt sein kann. Wenn beide angegeben werden, wird configuration_value verwendet. Wenn keines angegeben ist, ist die Eigenschaft der zurückgegebenen Configuration-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_reference": "ShoppingCart:Big" 
                    },  
                    { 
                        "name": "Small", 
                        "configuration_value": {
                            "Size": 300
                        }
                    } 
                ]
            }
        ]
    },

    "ShoppingCart": {
        "Big": {
            "Size": 600,
            "Color": "green"
        },
        "Small": {
            "Size": 300,
            "Color": "gray"
        }
    }
}

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_reference": "ShoppingCart:Big" 
    },  
    { 
        "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 ein Aufrufer überprüft, ob eine Kennzeichnung mit Varianten aktiviert ist, überprüft der Featureverwalter, ob die dem aktuellen Benutzer zugewiesene Variante so eingerichtet 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 einer Status von Disabled 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 unterstützt das Ausstrahlen dieser Ereignisse über Telemetrie-Herausgeber. Ein oder viele Telemetrie-Herausgeber können registriert werden, um Ereignisse zu veröffentlichen, wenn Featurekennzeichnungen ausgewertet werden.

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.

Benutzerdefinierte Telemetrie-Herausgeber

Die benutzerdefinierte Behandlung von Telemetrie für Featurekennzeichnungen wird durch Implementieren von ITelemetryPublisher und Registrieren im Featureverwalter ermöglicht. Wenn eine Featurekennzeichnung mit aktivierter Telemetrie ausgewertet wird, erhält der registrierte Telemetrieherausgeber die Möglichkeit, das entsprechende Auswertungsereignis zu veröffentlichen.

public interface ITelemetryPublisher
{
    ValueTask PublishEvent(EvaluationEvent evaluationEvent, CancellationToken cancellationToken);
}

Den EvaluationEvent-Typ finden Sie hier als Referenz.

Das Registrieren von Telemetrieherausgebern erfolgt beim Aufrufen von AddFeatureManagement(). Hier ist ein Beispiel zum Einrichten der Featureverwaltung zum Ausgeben von Telemetrie mit einer Implementierung von ITelemetryPublisher namens MyTelemetryPublisher.

builder.services
    .AddFeatureManagement()
    .AddTelemetryPublisher<MyTelemetryPublisher>();

Application Insights Telemetry-Herausgeber

Das Microsoft.FeatureManagement.Telemetry.ApplicationInsights-Paket bietet eine integrierte Implementierung von Telemetrieherausgebern, die Auswertungsdaten der Featurekennzeichnung 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()
    .AddTelemetryPublisher<ApplicationInsightsTelemetryPublisher>();

Hinweis

Das Basispaket Microsoft.FeatureManagement enthält diesen Telemetrieherausgeber nicht.

Ein Beispiel für die Verwendung finden Sie im Beispiel EvaluationDataToApplicationInsights.

Voraussetzungen

Dieser Telemetrieherausgeber hängt davon ab, dass Application Insights bereits eingerichtet und als Anwendungsdienst registriert ist. Dies geschieht beispielsweise hier in der Beispielanwendung.

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.

Wenn Sie erfahren möchten, wie Sie Experimente mit Variantenfeatureflags ausführen, fahren Sie mit dem folgenden Tutorial fort.