Innovate Your Software Faster without Risk

A Fast, Scalable, and Open-source Feature Flags Management Service. For Cloud & Self-hosting.

Comment mettre en œuvre un feature flag dans asp.net core blazor

Last updated date:

Cet article a été écrit par LifeCycle. Pour plus d'informations, consultez la version anglaise.

Suivez-moi sur Twitter, je suis heureux de prendre en compte vos suggestions sur les sujets ou les améliorations.

Introduction

De nombreux services de signalement de fonctionnalités tiers sont disponibles, ou votre équipe interne pourrait développer son propre service de signalement de fonctionnalités. Pour ceux qui préfèrent la standardisation, il est également possible de suivre les directives OpenFeature. Cependant, aucune de ces solutions ne correspond parfaitement à vos besoins, en particulier dans un projet Blazor, qui est un terrain relativement nouveau pour beaucoup. Même la bibliothèque Microsoft.FeatureManagement ne propose pas un support complet pour Blazor.

Dans cet article de blog, je vais partager mes connaissances sur la façon d'implémenter des indicateurs de fonctionnalités dans Blazor en utilisant un outil de signalement de fonctionnalités tiers.

J'ai expérimenté différentes méthodes, et dans cet article, je vais présenter les approches suivantes pour implémenter des indicateurs de fonctionnalités dans Blazor :

  1. La méthode traditionnelle : Utiliser des instructions if/else pour contrôler vos fonctionnalités (ou blocs de code). Cette méthode est applicable à la fois côté serveur et côté client.
  2. Utiliser des composants au lieu de TagHelper dans Blazor : Cette approche encapsule le bloc de code de le feature flag côté client et est efficace pour le rendu côté serveur (SSR) et WebAssembly.
  3. Attribut de porte de fonctionnalité personnalisé pour les actions du contrôleur : Si un feature flag n'est pas activé pour une requête, une erreur 404 sera renvoyée.
  4. Filtrage des routes : Cela contrôle l'accès aux pages. Si un feature flag n'est pas activé pour une requête, elle sera redirigée vers une page 404.

J'espère recevoir des commentaires des développeurs Blazor et je mettrai à jour cet article de blog en conséquence. Cliquez ici pour télécharger le Code Source utilisé dans cet article.

Créer une application Web Blazor Asp.Net Core 8

Je vais présenter les méthodes en utilisant une simple application Web Blazor. Vous pouvez créer une nouvelle application Web Blazor Asp.Net Core 8 en sélectionnant "Blazor Web App" et en cliquant sur "Suivant".

Donnez un nom à votre projet et cliquez sur "Suivant". Ensuite, configurez le projet comme indiqué ci-dessous et cliquez sur "Créer".

  • .NET 8
  • Configurer pour HTTPS
  • Mode de rendu interactif : Auto (Côté serveur et WebAssembly)
  • Emplacement d'interactivité par page/composant

Vous disposez maintenant d'un projet d'application Web Blazor. Exécutez le projet pour afficher la page par défaut. Nous allons commencer à implémenter le feature flag dans ce projet.

Choisissez un outil de signalement de fonctionnalités tiers

Il existe de nombreux outils de signalement de fonctionnalités tiers disponibles, notamment LaunchDarkly, Unleash et Microsoft.FeatureManagement. Cependant, dans cet article de blog, j'utiliserai FeatBit pour plusieurs raisons :

  • FeatBit est un projet open source avec un plan gratuit étendu. Il est largement utilisé par les entreprises qui utilisent principalement .NET comme framework.
  • Les services backend du projet sont développés en .NET et incluent un SDK .NET robuste mis à jour en temps réel.
  • FeatBit propose un service complet de gestion des indicateurs de fonctionnalités, plutôt qu'une simple bibliothèque d'indicateurs de fonctionnalités.

Installer et initialiser le SDK de feature flag

Dans le projet serveur de votre application Web Blazor, installez le SDK FeatBit .NET à l'aide du gestionnaire de packages NuGet.

Suivez le tutoriel du SDK pour ajouter le service FeatBit à votre fichier Program.cs afin d'initialiser le SDK.

// Ajouter le service FeatBit
builder.Services.AddFeatBit(options =>
{
    options.EnvSecret = "<remplacez-par-votre-secret-env>";
    options.StreamingUri = new Uri("ws://localhost:5100");
    options.EventUri = new Uri("http://localhost:5100");
    options.StartWaitTime = TimeSpan.FromSeconds(3);
});

Voici à quoi cela ressemble dans le fichier Program.cs du projet :

Maintenant que le SDK est initialisé, nous pouvons commencer à implémenter le feature flag dans notre application Web Blazor.

Méthode traditionnelle : Utiliser des instructions if/else pour contrôler vos fonctionnalités (ou blocs de code)

Cette méthode peut être appliquée à la fois côté serveur et côté client, offrant une approche simple. Elle offre la flexibilité de contrôler les fonctionnalités (ou blocs de code) dans les deux domaines.

Par exemple, si je veux ajouter une nouvelle phrase de bienvenue sur la page d'accueil et la contrôler à l'aide d'un feature flag, je ferais ce qui suit :

  1. Injectez le service en ajoutant le code suivant au fichier Home.razor :
@inject IFbClient FeatureFlags
  1. Dans le bloc de code Razor, après le code "Hello World" d'origine, ajoutez ceci :
@if (FeatureFlags.FeatureReleased("weather-page"))
{
    <h5>
        Bienvenue sur notre site web ! Nous sommes ravis de vous avoir ici et avons hâte de partager notre parcours avec vous.
    </h5>
}

Le code ci-dessus montre que FeatureFlags est le service injecté à l'étape précédente. FeatureReleased est la méthode utilisée pour vérifier si le feature flag est activé, avec la clé de le feature flag en tant que paramètre. Lorsque le feature flag est activé, le bloc de code "Phrase de bienvenue" sera rendu.

Voici à quoi cela ressemble dans le fichier Home.razor du projet :

REMARQUE : La méthode FeatureReleased n'est pas fournie par FeatBit ; c'est une extension que j'ai créée pour encapsuler la méthode BoolVariation de FeatBit. Si vous examinez le code de l'extension, vous verrez qu'il est assez simple :

Le SDK FeatBit nécessite un paramètre utilisateur pour aider à identifier l'utilisateur. Dans cet exemple, j'ai passé null, ce qui générera un utilisateur avec un ID aléatoire dans le but de simplifier notre démonstration. Cependant, dans une application réelle, vous devriez passer un objet utilisateur avec un ID unique :

  • Si l'utilisateur est connecté, passez l'ID utilisateur, le nom et toute autre information qui pourrait être utile pour la version de la fonctionnalité.
  • Si l'utilisateur n'est pas connecté, passez un ID aléatoire ou un ID de cookie. Assurez-vous que le même utilisateur final obtiendra toujours le même ID.

Pour plus d'informations, consultez le tutoriel du SDK. Après avoir implémenté le feature flag dans le code, vous remarquerez peut-être que le feature flag est toujours désactivé lorsque vous lancez le projet. Cela se produit car la méthode BoolVariation renvoie false par défaut. Pour activer le feature flag, accédez au tableau de bord FeatBit, créez un feature flag nommé "welcome-sentence" et activez-le.

Créer un feature flag dans le tableau de bord FeatBit

  1. Accédez à la page "Feature Flags" et cliquez sur le bouton vert + Ajouter dans le coin supérieur droit.
  2. Dans le volet contextuel, nommez le feature flag "welcome-sentence".
  1. Choisissez boolean comme type.
  2. Laissez les autres champs avec leurs valeurs par défaut et cliquez sur Enregistrer.

Pour afficher la "Phrase de bienvenue" aux utilisateurs, il vous suffit de relancer le projet et d'activer le feature flag dans le tableau de bord. Vous pouvez également déployer la fonctionnalité progressivement. Voici comment procéder :

Activez le feature flag dans le panneau de gauche. Dans le panneau de droite, configurez la règle par défaut pour renvoyer une valeur true pour 100 % des utilisateurs finaux (ou requêtes).

Méthode 2 : Utilisez un composant pour contrôler vos fonctionnalités

Utilisation de composants au lieu de TagHelper dans Blazor : cette approche encapsule le bloc de code du feature flag dans le frontend et est efficace à la fois pour le Server-Side Rendering (SSR) et WebAssembly. Cette méthode est similaire à la précédente, mais au lieu d'utiliser des instructions if/else, nous utiliserons un composant pour encapsuler le bloc de code du feature flag.

Le composant FeatureFlag est un composant simple qui prend une clé de feature flag comme paramètre et affiche le contenu enfant si le feature flag est activé. Voici comment je conçois et implémente ce composant :

Le composant FeatureFlag est un composant simple qui accepte une clé de feature flag comme paramètre. Il affiche le contenu enfant uniquement si le feature flag est activé. Ceci est réalisé en utilisant un composant partagé et la méthode FeatureReleased pour vérifier l'état du feature flag. Si le flag est activé, le contenu enfant est affiché.

Ceci est réalisé en utilisant un composant partagé et la méthode FeatureReleased pour vérifier l'état du feature flag. Si le flag retourne true, le contenu enfant est affiché. J'ai implémenté ce composant à la fois dans un projet SSR et dans un projet WebAssembly. Actuellement, j'explore des méthodes plus efficaces pour obtenir cette fonctionnalité mais je n'ai pas encore trouvé d'alternative. Si vous avez des suggestions ou connaissez une meilleure approche, n'hésitez pas à les partager.

Méthode 3 : Attribut personnalisé FeatureGate pour les actions de contrôleur

Contrairement aux deux méthodes précédentes, cette méthode est spécifiquement applicable au backend. Elle contrôle l'accès à une action de contrôleur. Si un feature flag n'est pas activé pour un utilisateur/une requête, la méthode renverra une erreur 404.

Dans ce projet, j'ai créé un contrôleur API nommé WeatherForecastController. Ce contrôleur inclut des API pour des algorithmes de prévisions météorologiques spéciaux. Par exemple, pour obtenir la prévision de la qualité de l'air en SO2 pour les 7 prochains jours, vous pouvez appeler l'API api/WeatherForecast/AirQualitySO2Algo. Cependant, l'accès à cette API est restreint et disponible uniquement pour les utilisateurs ou les requêtes autorisés.

Le code suivant montre comment j'utilise un attribut FeatureGate personnalisé pour contrôler l'accès à cette API :

  • Ajoutez l'attribut FeatureGate à l'action API api/WeatherForecast/AirQualitySO2Algo.
  • Définissez la clé de feature flag air-quality-so2-algo comme premier paramètre d'attribut.
  • Définissez regression comme valeur par défaut. Cela signifie que par défaut (par exemple, si aucun feature flag correspondant n'est créé), le feature flag renverra la valeur regression.
  • Définissez metnet comme l'une des valeurs autorisées. Cela signifie que si le feature flag ne renvoie pas metnet, l'API renverra une erreur 404.

L'implémentation d'un attribut pour contrôler l'accès à l'API est simple et efficace. C'est avantageux car cela permet d'identifier facilement quelles API sont contrôlées par des feature flags. De plus, changer la clé du feature flag dans l'attribut est simple.

Examinons l'implémentation de cet attribut personnalisé. Dans la méthode OnActionExecutionAsync, j'utilise la méthode StringVariation du SDK FeatBit pour vérifier l'état du feature flag. Si le feature flag ne renvoie pas une valeur définie dans la liste de chaînes PassedValues, une erreur 404 est renvoyée.

Vous pouvez développer votre propre logique pour un attribut personnalisé de feature flag. L'exemple fourni est basique, mais vous pouvez ajouter plus de paramètres à l'attribut pour une plus grande flexibilité. Vous pouvez également utiliser d'autres méthodes de variation, telles que BoolVariation, DoubleVariation, JsonVariation, etc.

Méthode 4 : Filtrage des routes

J'explore également une méthode pour centraliser le contrôle d'accès aux pages. Cela éliminerait le besoin d’intégrer des blocs de code de feature flag dans chaque page individuelle. Dans Blazor, le composant Router prend en charge une fonctionnalité OnNavigateAsync. Le gestionnaire OnNavigateAsync est appelé lorsque l'utilisateur :

  • Visite une route pour la première fois en y accédant directement dans son navigateur.
  • Navigue vers une nouvelle route à l’aide d’un lien ou d’une invocation de NavigationManager.NavigateTo.

Par conséquent, j'ai tenté de centraliser le contrôle des routes au sein de la méthode OnNavigateAsync dans le fichier Routes.razor.

En examinant la méthode FeatureFlags.PageAllowAccess, nous constatons qu'elle utilise un seul feature flag, route-navigation, pour contrôler tous les itinéraires. Le chemin est transmis en tant qu'attribut personnalisé pour FbUser, offrant une approche de gestion simple et flexible. Cela signifie que nous pouvons ajouter de nouvelles routes à l'avenir sans avoir besoin de créer de nouveaux feature flags ou de modifier le code existant pour les stratégies de publication de routes.

La stratégie de publication doit être configurée dans l'interface des feature flags FeatBit. La figure ci-dessous montre que seuls les utilisateurs correspondant à des conditions spécifiques peuvent accéder à la page météo.

Pour contrôler l'accès à davantage de pages, ajoutez simplement de nouvelles règles de ciblage personnalisées.

Libérer les fonctionnalités de manière flexible et progressive

L'ajout d'une nouvelle page et le contrôle de sa publication sont un scénario courant dans la gestion des feature flags. Par exemple, vous souhaiterez peut-être initialement diffuser la page à 10 % des utilisateurs, puis augmenter progressivement ce taux jusqu'à 100 %. FeatBit propose une méthode simple pour y parvenir.

En règle générale, cela nécessite de passer des utilisateurs (ou d'autres contextes) pour identifier chaque appel au feature flag. Cela garantit qu'un utilisateur reçoit systématiquement le même résultat pour le même feature flag. Cette cohérence est cruciale pour des pratiques telles que les tests en production, les tests A/B et la publication progressive.

Voici un exemple de la façon dont j'ai implémenté cela dans mon projet. J'ai transmis un nom d'utilisateur dans la méthode FeatureReleased pour identifier l'utilisateur.

Dans l'interface des feature flags FeatBit, je peux inclure cet utilisateur dans la liste de ciblage individuel. Dans l'image ci-dessous, seuls les utilisateurs de la liste de ciblage individuel true ont accès à la fonctionnalité welcome-sentence.

Cette méthode permet des stratégies de publication flexibles et contrôlées, essentielles pour une gestion efficace des feature flags.

Conclusion

Dans la plupart des cas, vous pouvez utiliser une instruction if/else pour tout contrôler. Cependant, si vous visez à gérer vos feature flags de manière standardisée, vous pouvez utiliser les méthodes que j'ai introduites dans ce billet de blog. Vous êtes également encouragé à concevoir vos propres méthodes pour garantir que les feature flags sont utilisés de manière cohérente et facilement référençable. Cette approche facilite la suppression des feature flags obsolètes.

J'espère que vous trouverez ce billet de blog utile. Si vous avez des questions ou des suggestions, n'hésitez pas à me contacter sur Twitter. Dans la plupart des cas, vous pouvez utiliser une instruction if/else pour tout contrôler. Cependant, si vous souhaitez gérer vos feature flags de manière standardisée, vous pouvez utiliser les méthodes que j'ai présentées dans cet article de blog. Vous êtes également encouragé à concevoir vos propres moyens pour garantir que les feature flags sont utilisés de manière cohérente et facilement référençable. Cette approche facilite la suppression des feature flags obsolètes.

J'espère que vous trouverez cet article de blog utile. Si vous avez des questions ou des suggestions, n'hésitez pas à me contacter sur Twitter.