DEV Community

Cover image for How to use Feature Flags in a Blazor Application
Emanuele Bartolesi
Emanuele Bartolesi

Posted on • Updated on

How to use Feature Flags in a Blazor Application

On Azure exists a service to provide a central manage application settings and features, called Azure App Configuration.

It's a really useful service especially for applications running in the cloud because they are distributed by nature.
With Azure App Configuration you can spread all the configuration trough all the components and services of your application.

In this article I will show you how to use the feature management to enable or disable functionalities in your application without a new deploy or restart the application.

Create an App Configuration Store on Azure

To create a new App Configuration, from the Azure Portal, click on the search bar on the top and start typing "app configuration"

Image description

Click on create and fill the form with your information.

Image description

After the deployment, select the new App Configuration from your resource group.

Image description

From the left navigation pane, click on "Features Manager" under the section "Operations".

Click on "Add" to create a new Feature.

Image description

Enter the Feature flag name "counter" and enable the feature flag.

Image description

Repeat the operation and call the new feature "weather".

Configure the Blazor Application

For this post, I use a Blazor Server App because, at the moment, the WASM project is not supported.

Add the NuGet packages called "Microsoft.FeatureManagement.AspNetCore" and "Microsoft.Azure.AppConfiguration.AspNetCore".

In the file "Program.cs", replace the code at line number 7 with the snippet below.


var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    WebRootPath = "wwwroot"
});

builder.WebHost.ConfigureAppConfiguration(config =>
            {
                config.AddAzureAppConfiguration(options =>
                    options.Connect("CONNECTIONSTRING").UseFeatureFlags());
            });
Enter fullscreen mode Exit fullscreen mode

Replace the CONNECTIONSTRING with the Azure App Configuration connection string from Azure Portal.

Image description

Create a new razor component on the project root called "FeatureFlagComponent.razor".

Replate the existing code in the file with the code below:

@using Microsoft.FeatureManagement
@inject IFeatureManager FeatureManager

@if (featureIsEnabled)
{
    @ChildContent
}

@code {
    private bool featureIsEnabled = false;

    [Parameter] public RenderFragment ChildContent { get; set; }
    [Parameter] public string FlagName { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (string.IsNullOrEmpty(FlagName)) return;
        featureIsEnabled = await FeatureManager.IsEnabledAsync(FlagName);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now you are ready to use this new component in your code.
For instance, we want to hide or show a menu entry on the navigation bar.
Open the file NavMenu.razor and replace the two menu entries with this piece of code:

        <FeatureFlagComponent FlagName="counter">
            <div class="nav-item px-3">
                <NavLink class="nav-link" href="counter">
                    <span class="oi oi-plus" aria-hidden="true"></span> Counter
                </NavLink>
            </div>
        </FeatureFlagComponent>

        <FeatureFlagComponent FlagName="weather">
            <div class="nav-item px-3">
                <NavLink class="nav-link" href="fetchdata">
                    <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
                </NavLink>
            </div>
        </FeatureFlagComponent>

Enter fullscreen mode Exit fullscreen mode

Now you can try to enable or disable the features from Azure and see the menu entries that appear or disappear on the navigation menu.

Image description

Top comments (6)

Collapse
 
michaelswells profile image
Michael S Wells • Edited

You are only hiding the link to the feature. I added the @attribute [FeatureGate("Counter")] to the top of the page (and even tried on the code behind page) and I could still type in the path to the counter page and was allowed to access the page and interact with it.
BTW, I am not using Azure. My appsettings.{envionment}.json file has the configuration:

{
  ...
  "FeatureManagement": {
   "Counter": true
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kanachrisi profile image
kanachrisi

Could you show the screenshot of where you added the attribute?
Thanks mate.

Collapse
 
michaelswells profile image
Michael S Wells • Edited

My comment was based on the article that you are only hiding the link in the menu. However, one can still navigate to the page by typing in the URL.

This is what my page named FeatureDetail.razor contains

@attribute [Route(Constants.Pages.Application.Features)]
@attribute [FeatureGate(nameof(ApplicationFeatures.ManageFeature))]
@inject IFeatureManager FeatureManager

<PageTitle>Feature Management</PageTitle>

<FeatureFlag FlagName="@featureName">
  <h1>This is the Feature Management page</h1>
</FeatureFlag>

@code
{
  //private bool featureIsEnabled = false;
  private string featureName = nameof(ApplicationFeatures.ManageFeature);

  protected override async Task OnInitializedAsync()
  {
    //featureIsEnabled = await FeatureManager.IsEnabledAsync(featureName);
  }

}

Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
michaelswells profile image
Michael S Wells

This is my FeatureFlag.razor file (based on your FeatureFlagComponent.razor file):

@using Microsoft.FeatureManagement
@inject IFeatureManager FeatureManager

@if (featureIsEnabled)
{
  @ChildContent
}

@code {
  private bool featureIsEnabled = false;

  [Parameter] public RenderFragment? ChildContent { get; set;  }
  [Parameter] public string? FlagName { get; set; }
  [Parameter] public bool Negate { get; set; } = false;

  protected override async Task OnInitializedAsync()
  {
    if (string.IsNullOrEmpty(FlagName))
    {
      return;
    }

    featureIsEnabled = await FeatureManager.IsEnabledAsync(FlagName);
    if(Negate)
    {
      featureIsEnabled = !featureIsEnabled;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
pjirsa profile image
Phil Jirsa

This would only work for Blazor server-side, right? Not Blazor WebAssembly.

Collapse
 
kasuken profile image
Emanuele Bartolesi

yes, exactly. "For this post, I use a Blazor Server App because, at the moment, the WASM project is not supported."