Cloud based applications are distributed in nature. As the times go it becomes more and more difficult to maintain an overview over all settings used across all of the components. Finally there is a new Azure service to store and manage application and deployment settings and feature flags in one place.

Prerequisites

For the simplicity all code samples are made in console application. You need to install Microsoft.Extensions.Configuration.AzureAppConfiguration and Microsoft.FeatureManagement NuGet packages and create new instance of Azure App Configuration (AAC) and Azure Key Vault.

To connect to AAC configure the ConfigurationBuilder with the AddAzureAppConfigurationextension method.

var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddAzureAppConfiguration(_ => _.Connect(new Uri("https://[your-app-configuration-service-name].azconfig.io"), new DefaultAzureCredential()));
IConfiguration configuration = configurationBuilder.Build();

I’m using all the time DefaultAzureCredential instance to connect to. This is an elegant way to not to expose some credentials in any unintentional way. To by able to read any data from AAC you need to assign yourself App Configuration Data Reader role if you use DefaultAzureCredential. This is not necessary if you go over connection string which is an another option.

Configuration Management

AAC use key-value store to persist application settings. First scenario what I want to show you is read simple configuration value. Just create new entry in Configuration Explorer with the key name TestApp:Settings:WelcomeMessage.

The colon in the key name ist a section separator. The configuration entry above is the same as this one in appsettings.json.

{
  "TestApp":  {
    "Settings": {
      "WelcomeMessage":  "Hello from local appsettings.json!"
    }
  }
}

Now you can read the data in the same way as from any other configuration provider.

Console.WriteLine(configuration["TestApp:Settings:WelcomeMessage"]);

Labels

There is one great feature which I personally call the “third configuration dimension”. It is possible to set labels to differentiate key values with the same key identifier. For this create new configuration entry TestApp:Settings:DbConnectionString with two values and label one as a Test.

Calling configuration["TestApp:Settings:DbConnectionString"] returns value without a label. To obtain value for the Test label filter need to be set by calling Select.

configurationBuilder.AddAzureAppConfiguration(_ =>
            {
                _.Connect(new Uri("https://ac-playground-dev.azconfig.io"), new DefaultAzureCredential());
                _.Select("*", "Test");
            });

You can also use the label to create multiple versions of the same key, where the label is the version number of the key.

Referencing Key Vault

You can also reference values from Key Vault which enables to use AAC as a single point of access to all configurations data. AAC doesn’t copy the values of Key Vault into his own key-value store, rather it stores Key Vault URIs as a reference. The AAC library still use Key Vault to retrieve those values but this is transparent. You are still responsible to authenticate your application against Key Vault properly. For this demo you must set Access Policies in your Key Vault to be able to read the secrets.

Add new Key Vault reference into AAC as a TestApp:Settings:WelcomeSecretMessage.

To access the Key Vault from your application you need to call ConfigureKeyVault in AddAzureAppConfiguration.

var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddAzureAppConfiguration(_ =>
            {
                _.Connect(new Uri("https://ac-playground-dev.azconfig.io"), new DefaultAzureCredential());
                _.ConfigureKeyVault(_ => _.SetCredential(new DefaultAzureCredential()));
            });
IConfiguration configuration = configurationBuilder.Build();
Console.WriteLine(configuration["TestApp:Settings:WelcomeSecretMessage"]);

Dynamic Configuration

AAC support dynamic configuration based on the sentinel key. This is a special key which indicates that the configuration changes has been finished and the application can reload new values. Basically it prevents partial updates which can lead to undesirable side effects.

First add new key TestApp:Settings:Sentinel. The value isn’t important it can be anything. Than configure provider with the ConfigureRefresh method.

var configurationBuilder = new ConfigurationBuilder();
IConfigurationRefresher configurationRefresher = null;
configurationBuilder.AddAzureAppConfiguration(_ =>
            {
                _.Connect(new Uri("https://ac-playground-dev.azconfig.io"), new DefaultAzureCredential());
                _.ConfigureRefresh(_ =>
                    _.Register("TestApp:Settings:Sentinel", true));
                _.ConfigureKeyVault(_ => _.SetCredential(new DefaultAzureCredential()));
                configurationRefresher = _.GetRefresher();
            });
IConfiguration configuration = configurationBuilder.Build();
Console.WriteLine(configuration["TestApp:Settings:WelcomeMessage"]);
Console.WriteLine("Press any key when configuration has been refreshed...");
Console.ReadLine();
await configurationRefresher.TryRefreshAsync();
Console.WriteLine(configuration["TestApp:Settings:WelcomeMessage"]);

In this sample I obtain instance of IConfigurationRefresher to refresh data. This only happen when the value of the sentinel key has been changed. ASP.NET Core application supports automatic refreshing using IOptionsSnapshot<T> pattern.

dotnet run
Hello from App Configuration!
Press any key when configuration has been refreshed…
App Configuration has been refreshed!

Feature Management

Feature flags are powerful technique to modify the system behavior without changing the code. It is the central concept of Lean Product Development to enable A/B tests, canary releases, betas and so on. AAC supports feature flags with the Microsoft.FeatureManagement client library. ASP.NET Core applications supports also declarative way to check when feature flags are enabled or not to avoid writing if statements.

Note: To simplify AddAzureAppConfiguration I deleted all entries from my AAC instance to focus on feature management.

To enable feature management call UseFeatureFlags.

var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddAzureAppConfiguration(_ =>
{
    _.Connect(new Uri("https://ac-playground-dev.azconfig.io"), new DefaultAzureCredential());
    _.UseFeatureFlags();
});
IConfiguration configuration = configurationBuilder.Build();

Create new feature flag TestApp.Settings.FeatureFlags.FeatureA in AAC Feature Manager.

Now comes feature management client library into the game. To examine if the feature is on or off an instance of IFeatureManager is needed. To be able obtain this register feature management in the dependency injection container by calling AddFeatureManagement.

IServiceCollection services = new ServiceCollection();
services
    .AddSingleton(configuration)
    .AddFeatureManagement();
ServiceProvider serviceProvider = services.BuildServiceProvider();

With the IFeatureManager instance get the current state of the feature flag.

var featureManager = serviceProvider.GetRequiredService<IFeatureManager>();
bool isFeatureAEnabled = await featureManager.IsEnabledAsync("TestApp.Settings.FeatureFlags.FeatureA");
Console.WriteLine($"Feature A enabled: {isFeatureAEnabled}");

Source Code

https://github.com/kalcik/blog-samples/tree/master/AzureApplicationConfiguration

About the Author Anton Kalcik

Most of the time, I assist people in the creation of valuable software. I’m a software engineer and entrepreneur specializing in .NET and Microsoft Azure. I offer Code Katas, Coding Dojos, workshops and talks about .NET, Microsoft Azure, DevOps, Agile Methodologies and Clean Code. I'm founder of CoderDojo Wien and president of digital.austria association.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.