One of fundamentals of The Twelve-Factor is the strict separation of config from code and storing them in environment variables.
A common way is to store default values in JSON or XML files and have the possibility to override them with environment variables.
That's why in ASP.NET Core, we usually find this kind of builder:
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
-
appsettings.json
contains all the default configuration. -
appsettings.{env}.json
is merged with the default one. In this case the environment name is required as an environment variable. - Finally the merged values are overridden by environment variables having the same name.
But what if we have to support System.Configuration.ConfigurationManager
?
ConfigurationManager
With ConfigurationManager
there are instead XML files, such as app.config
and app.{env}.config
.
Unfortunately the artefact cannot be immutable and be shipped with all environments conf.
During the build process, the final config file is transformed with a XDT tool (Xml Document Transformation).
Since .NET Framework 4.7.1, there is a handy NuGet that allows us to override the default values by environment variables.
- Add Microsoft.Configuration.ConfigurationBuilders.Environment NuGet.
- Add the following markup in the config file:
<configuration>
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration" restartOnExternalChanges="false" requirePermission="false" />
</configSections>
<configBuilders>
<builders>
<add name="EnvConfigBuilder" type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Environment" />
</builders>
</configBuilders>
<appSettings configBuilders="EnvConfigBuilder">
...
</appSettings>
<connectionStrings configBuilders="EnvConfigBuilder">
...
</connectionStrings>
</configuration>
- If an environment variable with the same key/name exists, then it will be overridden during execution.
💡 For more details please follow the documentation.
Azure Key Vault
It's best to stick with the Twelve-Factor methodology for your App Service or Azure Functions and to not use other ConfigurationBuilders
libraries.
For this you can setup Key Vault references.
So without requiring any code changes, all secrets will be added as environment variables and consumed by EnvironmentConfigBuilder
.
Tips
If environment variable names cannot match the config, it's possible to customize like this:
using Microsoft.Configuration.ConfigurationBuilders;
public class EnvConfigBuilder : EnvironmentConfigBuilder
{
public override string GetValue(string key) => key switch
{
"MyConfName" => base.GetValue("MyEnvVarName"),
_ => null // means do not override the default value
}
}
<configBuilders>
<builders>
<add name="EnvConfigBuilder" type="MyNamespace.EnvConfigBuilder, MyAssemblyName" />
</builders>
</configBuilders>
Resources
aspnet / MicrosoftConfigurationBuilders
Microsoft.Configuration.Builders
Configuration Builders
ConfigurationBuilders are a feature of the full .Net Framework that were introduced in .Net 4.7.1. You can read about the concept in this blog post. While the framework for executing configuration injection now exists in .Net as of 4.7.1 with that feature, the framework does not ship with any pre-made builders in box. The goal of this project is for Microsoft to provide a basic set of Configuration Builders that should make it easy for developers to leverage this feature in their apps. They are also intended to address some of the basic dynamic/non-local configuration needs of applications as they move into a container and cloud focused environment.
The set of builders produced here are styled as "Key/Value Config Builders." The architecture of ConfigurationBuilder
in the framework is actually quite flexible and can be leveraged to handle a great number of unique situations. To keep things…
Top comments (0)