Overview

Feature management and Feature flags is not a new concept. It allows for merging features often and releasing code but not always turning it on. There have been many different tooling, styles, packages and extensions over the years. With the cloud, and specifically Azure, being pushed hard by Microsoft recently they have brought out a new feature management package which hooks into Azure nicely.

It is currently in the second iteration and making all the calls asynchronous. It can be used when running in Azure but also can be used with regular IConfiguration instance so let take a look at how to get it up and running in a simple console application.

Setting up the project

To allow for using the new Feature Management package you have to do very little to get it up and running.

  1. First create a new dot net core console application.

  2. Edit your csproj file to add the package references below.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.0" />
    <PackageReference Include="Microsoft.FeatureManagement" Version="2.0.0" />
  </ItemGroup>

</Project>

I’ve referrenced the entire contents of the csproj file to show how little is required to get this up and running.

  1. We now need to setup the configuration to use. Now the Feature Management setup expects, as default, there to be a configuration section called “FeatureManagement” and then the settings for the features beneath it.

To keep this as simple as possible I have setup an in memory configuration collection based on a dictionary. This has direct value reference syntax for configuration eg. “FeatureManagement:Beta”. This would be the same as …

{
    "FeatureManagement": {
        "Beta" : true
    }
}

… in an appsettings.json file. There are a lot of resources dedicated to how the IConfiguration ecosystem can be setup so will leave that with you to search.

  1. We now need to consume the configuration and register the Feature Management services.
var featureManagement = new Dictionary<string, string> {{ "FeatureManagement:Beta", "true"}};

IConfigurationRoot configuration = new ConfigurationBuilder().AddInMemoryCollection(featureManagement).Build();

IServiceCollection services = new ServiceCollection();
services.AddFeatureManagement(configuration);

As described earlier we have set it up to be an in memory configuration collection. Using a ConfigurationBuilder we have loaded the key/value pairs of configuration and created an instance of IConfigurationRoot. This is required for setting up the Feature Management services.

Once we have an instantiated IConfigurationRoot we can register the required services with the ServiceCollection instance. This is done through using the AddFeatureManagement extension method and passing in the configuration instance.

Now the services are all registered we move onto the consuming of the services.

  1. We now need to create an IServiceProvider to allow us to resolve the services and consume the functionality. This is done through the BuildServiceProvider() method on the IServiceCollection. This will create an instance of the default built in service provider implementation. Now we have a service provider we can resolve an instance of the IFeatureManager which has been setup and configured with our feature flags.
IServiceProvider serviceProvider = services.BuildServiceProvider();

IFeatureManager featureManager = serviceProvider.GetRequiredService<IFeatureManager>();
  1. Once we have a feature manager instance we can check to see if the named feature is enabled. This is an asynchronous call now and will require the method call to be awaited. In the earlier verisons of the library it was a synchronous call and due to the change in api surface I would guess it was a blocking operation under the hood. I’m guessing this would have had a performance impact somewhere but I’ve not investigated the library yet.
if (await featureManager.IsEnabledAsync("Beta"))
{
    Console.WriteLine("Welcome to the beta!");
}

Code in full

Below is the full program in full to see how it all fits together.

class Program
{
    static async Task Main(string[] args)
    {
        var featureManagement = new Dictionary<string, string> {{ "FeatureManagement:Beta", "true"}};

        IConfigurationRoot configuration = new ConfigurationBuilder().AddInMemoryCollection(featureManagement).Build();
        
        IServiceCollection services = new ServiceCollection();
        services.AddFeatureManagement(configuration);

        IServiceProvider serviceProvider = services.BuildServiceProvider();
        
        IFeatureManager featureManager = serviceProvider.GetRequiredService<IFeatureManager>();
        if (await featureManager.IsEnabledAsync("Beta"))
        {
            Console.WriteLine("Welcome to the beta!");
        }

        Console.WriteLine("Hello World!");
    }
}

Conclusion

In this post we have looked how to get the Feature Management packages into a console application. We have looked at the basic configuration settings which are required to get it working. We have registered the functionality and consumed the functionality to drive conditional logic at run time.

The code in this post has been based on the “beta” example which can be found - https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-feature-flag-aspnet-core?tabs=core3x

I look forward to looking more at this library and seeing what can be done.

Further reading: https://docs.microsoft.com/en-us/azure/azure-app-configuration/use-feature-flags-dotnet-core

Any questions/comments then please contact me on Twitter @WestDiscGolf