ArrowLinkToArchivePageBlog

How to manage feature flags in ASP.NET Core apps with Azure? Guide to creating an Azure App Configuration store

No matter how simple or complex an application is, choosing the right configuration provider right at the start will make it simpler for you to manage feature flags and add relevant filters later. As Azure App Configuration comes with many additional elements, it is my preferred option.

In my two previous articles, I described what feature flags are and how to implement them in .NET applications. The two posts are a good place to start if you need an overview first.

Once the feature management is set up, you will need to decide where to store the feature flag configuration.

And this is exactly what I’m going to discuss in this article.

Key points

  • Where can we store feature flag configuration?
  • How to integrate Azure App Configuration into ASP.NET Core apps?
  • Is it possible to change the feature flag value in real time without restarting the app?
  • How to provide configuration for feature filters?
  • Can the application cache and select only some feature flags from Azure App Configuration?

What is the best place to store the feature flag configuration?

Last time, I described Microsoft.FeatureManagement library and how much it helps with the feature flags implementation. It should come as no surprise to you that it will also come in handy here.

The Microsoft.FeatureManagement library operates on a standard ASP.NET Core configuration, so you can choose any available configuration provider.

An example would be environmental variables or appsettings.json files:

"FeatureManagement": {
    "UseExtremeScaling": false,
    "UsePromotionCoupons": {
        "EnabledFor": [
            {
                "Name": "Microsoft.Targeting",
                "Parameters": {
                    "DefaultRolloutPercentage": 1
                },
            },
        ],
    },
  },

Selecting the best configuration provider for feature management will depend heavily on the level of complexity of your application.

In the case of very simple apps, JSON files and environmental variables are probably enough.

However, when you implemented many different feature flags in the project and want a user friendly-portal to view and edit feature toggle configuration, Azure App Configuration is the place to go.

What is Azure App Configuration?

It is Azure cloud-based configuration storage that enables development teams to manage application parameters in real time without code deployments. The solution is fast, scalable, and secure.

From the feature toggle perspective, the killer functionality would be the built-in feature management support.

Also, its panel for feature flag administration is functional and visually attractive:

application configuration panel in Azure feature manager

In the panel, you can switch the simple on/off feature flags, and there is also a built-in configuration editor for feature filters such as:

  • Time window
  • Targeting
  • Custom (your own filters)

app configuration panel in Azure feature manager - filters

If you are unfamiliar with feature filters, I highly encourage you to check my previous article, where I describe them in more detail.

The other great benefit is the centralized feature management configuration storage. It will really come in handy if you deal with multiple (micro)services that use the same feature flags.

Last but not least is the integration with Microsoft.FeatureManagement, which is a real piece of cake.

Azure App Configuration is just another .NET configuration provider, so after connecting your app to it, you have feature flags automatically set up.

How to create a new Azure App Configuration store?

The easiest way to provision Azure App Configuration is to use Azure Portal.

Here’s what you need to do:

1. First, open Azure Portal and click on the ‘Create a resource’ button:

App configuration provisioning in Azure feature manager step 1

2. Then select the ‘App Configuration’ resource from the search bar:

App configuration provisioning in Azure feature manager step 2

3. On the next screen, click the ‘Create’ button:

App configuration provisioning in Azure feature manager step 3

4. Then we need to provide all the necessary details like the resource group, the location, the resource name, recovery options, and the pricing tier.

If you are unsure what to choose, check the pricing tiers in Azure Documentation to select the plan that suits your needs.

App configuration provisioning in Azure feature manager step 4

5. You can then add some tags and set up networking for Azure App Configuration (e.g., to allow access only for a specific Azure Virtual Network).

We will skip this step for brevity here and click ‘Review + Create.’

When the validation passes, we can provision Azure App Configuration using the ‘Create’ button:

App configuration provisioning in Azure feature manager step 5

6. After a few minutes, Azure App Configuration should be created and ready to use:

App configuration provisioning in Azure feature manager step 6

7. Finally, we can go to the resource page to see our Azure App Configuration overview:

App configuration provisioning in Azure feature manager step 7

Some interesting subpages to explore now are:

  • Access Keys – where you can grab an access key needed to connect your app with the resource
  • Feature Manager – a feature flags management screen I’ve shown you at the beginning of this post

Let’s leave Azure Portal for a while now and go to the application source code, where we will connect the application with Azure App Configuration.

How to add Azure App Configuration to your project?

At this point, I guess that you already have the Microsoft.FeatureManagement library added to your application.

If you are not sure how to do that, you can find more instructions and follow the steps described in my previous article.

As usual, we will start with installing the NuGet package:

dotnet add package Microsoft.Azure.AppConfiguration.AspNetCore

Then we can register Azure App Configuration as a configuration provider with the code below:

// Program.cs
Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
        webBuilder.ConfigureAppConfiguration(config =>
        {
            var settings = config.Build();
            config.AddAzureAppConfiguration(appConfig =>
                appConfig.Connect(settings["AppConfig:ConnectionString"].UseFeatureFlags())
        }).UseStartup<Startup>());

What it does is retrieve the Azure App Configuration connection string from the current configuration and then register Azure App Configuration as the new configuration provider.

UseFeatureFlags method enables Azure App Configuration to store its feature flags under the FeatureManagement configuration section, which is exactly the place where Microsoft.FeatureManagement needs it.

This behavior can be configured, and we will get back to the code part soon.

The next step is to register Azure App Configuration in a DI container and add specific middleware to a request pipeline.

using Microsoft.Extensions.Configuration;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddAzureAppConfiguration(); // <- Add this line
        // ...
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        
        app.UseAzureAppConfiguration(); // <- Add this line
        app.UseHttpsRedirection();
        app.UseRouting();

       // ...
    }
}

Before launching the app, we need to provide an Azure App Configuration connection string. We can find it in Azure Portal on the Access Keys subpage.

Providing an Azure App Configuration connection string

It is also possible to set up the connection without any access keys but by using Azure Active Directory-managed identities for authentication.

To keep this tutorial as simple as possible, I won’t present it here, but for production usage, I recommend checking this site to find out more.

Okay, let’s copy the connection string to use in the app.

When initializing the app, we get the value for AppConfig:ConnectionString key.

In appsettings.json, this would look like this:

{
    "AppConfig" : {
        "ConnectionString" : "SECRET",
    }
}

Putting the connection string in the appsettings.json file is tempting, but as far as security is concerned, this would create a potential vulnerability. After all, it is sensitive data, so you need to store it with care.

Locally you can utilize the built-in ASP.NET Core user secrets and App Service Configuration in Azure Portal on production or, better still, Azure Key Vault.

And that’s it. Your application can now use Azure App Configuration as feature flag storage, and you may change the configuration in real time.

Let’s add the first feature flag to Azure App Configuration, shall we?

How to manage feature flags in Azure App Configuration?

First, we will add the UsePromotionCoupons feature flag to App Configuration.

In my previous article, we learned how to add it to the app, so check it out if you are not familiar with that.

We will start by navigating to the feature manager subpage in Azure Portal. Then, click the ‘Create’ button to add a new feature flag and give it a name.

creating a new feature flag step 1

The key will be filled automatically from the name, but we will get back to this later in this article.

We can also add a label (more details later in this post) and a description, enable the feature flag, and configure feature filters.

creating a new feature flag step 2

Finally, we can click ‘Apply.’ The feature flag will be created and visible on the feature manager subpage.

creating a new feature flag step 3

When you launch your application now, it should read the feature flag value from the App Configuration, and you can change its value from the feature manager page. No restart is needed!

But remember that the Azure App Configuration values are cached in your application.

By default, feature flags are cached for 30 seconds. Later in the article, I will show you how to change it.

How to configure feature filters?

By now, you know how to switch on/off feature flags in Azure App Configuration.

However, if you read my previous article, you probably remember that we can also use feature filters to turn on a feature flag when a specific condition is met.

The Microsoft.FeatureManagement library has two built-in filters:

  • Targeting – enables the feature for a specific group or a share of all app users (e.g., only 1% of all users will have access to the feature)
  • Time window – enables the feature flag for all users at a specified time (e.g., this weekend only)

Both of them are supported by Azure App Configuration, and you can easily set them up on the feature manager page.

Here’s an overview of the targeting feature filter:

adding a targeting filter in Azure Feature Manager

And the image below shows how to set up the second filter type, the time window:

adding a time window filter in Azure Feature Manager

After saving the changes, the filter will be synchronized with your app. When registered right, it should work without restarting the app (keep the cache, though!).

If for some reason, built-in filters are not what you want, there is yet another option: adding custom feature filters.

For example, in my previous article, I showed you how to build ClaimsCheckFeatureFilter, and we will follow the same approach here as well.

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.FeatureManagement;
namespace Predica.FeatureFlagsExample;

[FilterAlias("ClaimsCheck")]
public class ClaimsCheckFeatureFilter : IFeatureFilter
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public ClaimsCheckFeatureFilter(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
    {
        var settings = context.Parameters.Get<ClaimsCheckFeatureFilterSettings>()
                       ?? new ClaimsCheckFeatureFilterSettings();
        var strValue = _httpContextAccessor.HttpContext?.User.FindFirstValue(
            settings.ClaimType);
        var parsed = bool.TryParse(strValue, out var claimValue);
        var isFeatureOn = parsed && claimValue;
        return Task.FromResult(isFeatureOn);
    }
}

Here, you will need to adjust the settings for the ClaimType.

namespace Predica.FeatureFlagsExample;

public class ClaimsCheckFeatureFilterSettings
{
    public string ClaimType { get; set; }
}

You can store it in Azure App Configuration.

While on the edit page, select “Custom” and provide a name for it.

Remember to match it either with the type or the alias:

adding a custom filter in Azure Feature Manager

Then, add a parameter for the filter by selecting ‘edit filter parameters’ from the dropdown menu:

editing filter parameters in Azure feature manager step 1

Finally, provide the name for the parameter and its value:

editing filter parameters in Azure feature manager step 2

And that’s it! You have successfully set up a custom filter.

As was the case with other built-in filters, you don’t need to restart the app if the filter is registered in the app.

How to cache feature flags stored in Azure App Configuration?

I mentioned before that feature flags are cached by Azure App Configuration to avoid unnecessary usage of resources such as CPU or network bandwidth.

By default, feature flags are cached for 30 seconds, but we can easily change that in the application initialization:

// Program.cs
Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
        webBuilder
            .ConfigureAppConfiguration(config =>
            {
                var settings = config.Build();
                config.AddAzureAppConfiguration(appConfig =>
                    appConfig.Connect(settings["AppConfig:ConnectionString"])
                        .UseFeatureFlags(featureFlagsConfig =>
                        {
                            // Add this config
                            featureFlagsConfig.CacheExpirationInterval =
                                TimeSpan.FromSeconds(5);
                        }));
            })
            .UseStartup<Startup>());

CacheExpirationInterval property controls how much time must pass before updating the feature flags from App Configuration.

It can’t be less than a second, but there is no maximum value for a change expiration.

According to the code sample above, the application is configured to refresh the cache every five seconds.

How to filter feature flags?

If we have an application with a few feature flags and only one environment, then managing feature flags is pretty easy.

But what about some more complex scenarios?

Let’s assume that our application has two environments:

  • A development environment – used for development purposes only
  • A production environment – live application handling the real load

Imagine that we want to set feature flags with different values for each environment. For example, turn the feature on in the development environment but keep it off in the second one.

Of course, we can have a dedicated App Configuration per environment. However, that would be rather costly, so to reduce the cloud bill, we have only one instance to cover both app environments.

Luckily, Azure App Configuration offers a handy option called labels that will fit this scenario perfectly.

In a nutshell, you can have multiple feature flags with the same name but a different label, so your application will pick up feature flags with pre-defined labels only.

Here’s how you create one:

creating a feature flag with a pre-defined label in Azure feature manager

And later, you can enable it for a given environment:

enabling a feature flag for a given environment in Azure feature manager

To make it all work, however, we need to change the application initialization so that it can fetch flags with the labels you defined:

// Program.cs
Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
        webBuilder
            .ConfigureAppConfiguration(config =>
            {
                var settings = config.Build();
                config.AddAzureAppConfiguration(appConfig =>
                    appConfig.Connect(settings["AppConfig:ConnectionString"])
                        .UseFeatureFlags(featureFlagsConfig =>
                        {
                            featureFlagsConfig.CacheExpirationInterval = 
                                TimeSpan.FromSeconds(5);
                            
                            // Add this line
                            featureFlagsConfig.Label = settings["AppConfig:Label"];
                        }));
            })
            .UseStartup<Startup>());

The code above filters feature flags with the same labels that are provided in the app settings under the Label property in the AppConfig section.

You can store it in any configuration provider supported by your app, for example, in the appsettings.json file or environmental variables.

And if you set Label to dev for your development environment and prod for production one, your application will pick only eligible feature flags.

Summary

I hope I’ve given you enough evidence that App Configuration is a good choice for storing your feature flags. It will come in handy when you have many applications (maybe microservices?) that use the same feature flags.

Moreover, it has a convenient user interface for feature management, which helps to see the overview of all feature toggles in your system.

Last but not least, it integrates nicely with the powerful Microsoft.FeatureManagement library.

So, this was my third post about feature flags. You can watch out for the next (and the last) one, where I will cover some good practices for you to follow if you want to work with feature toggles.

And if you need someone to help you with your app, don’t forget to let us know.

Further reading

Microsoft.FeatureManagement library documentation

Azure App Configuration documentation

Key takeaways

  1. There is no need to use a separate configuration provider if you work with simple applications. However, when implementing many different feature flags in one project, or when your system is composed of many web applications, you may try using Azure App Configuration.
  2. The Azure storage allows you to manage parameters in real time and change values in the manager page without restarting the application.
  3. To limit the unnecessary usage of CPU or bandwidth, feature flags stored in Azure App Configuration are cached for 30 seconds, but you can change the settings manually.
  4. It is possible to set feature flags with different values for separate environments without running up a huge bill for cloud services.

See other articles in the series:

  1. What are feature flags, and how to use them?
  2. How to implement feature flags and filters in .NET apps?

Sign up for Predica Newsletter

A weekly, ad-free newsletter that helps cutomer stay in the know. Take a look.

SHARE

Want more updates like this? Join thousands of specialists who already follow our newsletter.

Stay up to date with the latest cloud insights from our CTO