Training
Module
Externalize the configuration of an ASP.NET app by using an Azure key vault - Training
Learn how to use ConfigurationBuilder to dynamically configure an ASP.NET web app to retrieve secrets from an Azure key vault.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Configuration in .NET is possible with configuration providers. Several types of providers rely on various configuration sources. This article details all of the different configuration providers and their corresponding sources.
FileConfigurationProvider is the base class for loading configuration from the file system. The following configuration providers derive from FileConfigurationProvider
:
Keys are case-insensitive. All of the file configuration providers throw the FormatException when duplicate keys are found in a single provider.
The JsonConfigurationProvider class loads configuration from a JSON file. Install the Microsoft.Extensions.Configuration.Json
NuGet package.
Overloads can specify:
Consider the following code:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using ConsoleJson.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.Sources.Clear();
IHostEnvironment env = builder.Environment;
builder.Configuration
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);
TransientFaultHandlingOptions options = new();
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
.Bind(options);
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
The preceding code:
Environment
.json files with the following options:
optional: true
: The file is optional.reloadOnChange: true
: The file is reloaded when changes are saved.Important
When adding configuration providers with IConfigurationBuilder.Add, the added configuration provider is added to the end of the end of the IConfigurationSource
list. When keys are found by multiple providers, the last provider to read the key overrides previous providers.
An example appsettings.json file with various configuration settings follows:
{
"SecretKey": "Secret key value",
"TransientFaultHandlingOptions": {
"Enabled": true,
"AutoRetryDelay": "00:00:07"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
From the IConfigurationBuilder instance, after configuration providers have been added, you can call IConfigurationBuilder.Build() to get the IConfigurationRoot object. The configuration root represents the root of a configuration hierarchy. Sections from the configuration can be bound to instances of .NET objects and later provided as IOptions<TOptions> through dependency injection.
Note
The Build Action and Copy to Output Directory properties of the JSON file must be set to Content and Copy if newer (or Copy always), respectively.
Consider the TransientFaultHandlingOptions
class defined as follows:
namespace ConsoleJson.Example;
public sealed class TransientFaultHandlingOptions
{
public bool Enabled { get; set; }
public TimeSpan AutoRetryDelay { get; set; }
}
The following code builds the configuration root, binds a section to the TransientFaultHandlingOptions
class type, and prints the bound values to the console window:
TransientFaultHandlingOptions options = new();
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
.Bind(options);
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
The application writes the following sample output:
// Sample output:
// TransientFaultHandlingOptions.Enabled=True
// TransientFaultHandlingOptions.AutoRetryDelay=00:00:07
The XmlConfigurationProvider class loads configuration from an XML file at run time. Install the Microsoft.Extensions.Configuration.Xml
NuGet package.
The following code demonstrates the configuration of XML files using the XML configuration provider.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.Sources.Clear();
builder.Configuration
.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true)
.AddXmlFile("repeating-example.xml", optional: true, reloadOnChange: true);
builder.Configuration.AddEnvironmentVariables();
if (args is { Length: > 0 })
{
builder.Configuration.AddCommandLine(args);
}
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
The preceding code:
optional: true
: The file is optional.reloadOnChange: true
: The file is reloaded when changes are saved.args
contain arguments.The XML settings are overridden by settings in the Environment variables configuration provider and the Command-line configuration provider.
An example appsettings.xml file with various configuration settings follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<SecretKey>Secret key value</SecretKey>
<TransientFaultHandlingOptions>
<Enabled>true</Enabled>
<AutoRetryDelay>00:00:07</AutoRetryDelay>
</TransientFaultHandlingOptions>
<Logging>
<LogLevel>
<Default>Information</Default>
<Microsoft>Warning</Microsoft>
</LogLevel>
</Logging>
</configuration>
Tip
To use the IConfiguration
type in WinForms apps, add a reference to the Microsoft.Extensions.Configuration.Xml NuGet package. Instantiate the ConfigurationBuilder and chain calls to AddXmlFile and Build(). For more information, see .NET Docs Issue #29679.
In .NET 5 and earlier versions, add the name
attribute to distinguish repeating elements that use the same element name. In .NET 6 and later versions, the XML configuration provider automatically indexes repeating elements. That means you don't have to specify the name
attribute, except if you want the "0" index in the key and there's only one element. (If you're upgrading to .NET 6 or later, you may encounter a break resulting from this change in behavior. For more information, see Repeated XML elements include index.)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<section name="section0">
<key name="key0">value 00</key>
<key name="key1">value 01</key>
</section>
<section name="section1">
<key name="key0">value 10</key>
<key name="key1">value 11</key>
</section>
</configuration>
The following code reads the previous configuration file and displays the keys and values:
IConfigurationRoot configurationRoot = builder.Configuration;
string key00 = "section:section0:key:key0";
string key01 = "section:section0:key:key1";
string key10 = "section:section1:key:key0";
string key11 = "section:section1:key:key1";
string? val00 = configurationRoot[key00];
string? val01 = configurationRoot[key01];
string? val10 = configurationRoot[key10];
string? val11 = configurationRoot[key11];
Console.WriteLine($"{key00} = {val00}");
Console.WriteLine($"{key01} = {val01}");
Console.WriteLine($"{key10} = {val10}");
Console.WriteLine($"{key10} = {val11}");
The application would write the following sample output:
// Sample output:
// section:section0:key:key0 = value 00
// section:section0:key:key1 = value 01
// section:section1:key:key0 = value 10
// section:section1:key:key0 = value 11
Attributes can be used to supply values:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<key attribute="value" />
<section>
<key attribute="value" />
</section>
</configuration>
The previous configuration file loads the following keys with value
:
key:attribute
section:key:attribute
The IniConfigurationProvider class loads configuration from an INI file at run time. Install the Microsoft.Extensions.Configuration.Ini
NuGet package.
The following code clears all the configuration providers and adds the IniConfigurationProvider
with two INI files as the source:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.Sources.Clear();
IHostEnvironment env = builder.Environment;
builder.Configuration
.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true)
.AddIniFile($"appsettings.{env.EnvironmentName}.ini", true, true);
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
An example appsettings.ini file with various configuration settings follows:
SecretKey="Secret key value"
[TransientFaultHandlingOptions]
Enabled=True
AutoRetryDelay="00:00:07"
[Logging:LogLevel]
Default=Information
Microsoft=Warning
The following code displays the preceding configuration settings by writing them to the console window:
foreach ((string key, string? value) in
builder.Configuration.AsEnumerable().Where(t => t.Value is not null))
{
Console.WriteLine($"{key}={value}");
}
The application would write the following sample output:
// Sample output:
// TransientFaultHandlingOptions:Enabled=True
// TransientFaultHandlingOptions:AutoRetryDelay=00:00:07
// SecretKey=Secret key value
// Logging:LogLevel:Microsoft=Warning
// Logging:LogLevel:Default=Information
Using the default configuration, the EnvironmentVariablesConfigurationProvider loads configuration from environment variable key-value pairs after reading appsettings.json, appsettings.Environment
.json, and Secret manager. Therefore, key values read from the environment override values read from appsettings.json, appsettings.Environment
.json, and Secret manager.
The :
delimiter doesn't work with environment variable hierarchical keys on all platforms. For example, the :
delimiter is not supported by Bash. The double underscore (__
), which is supported on all platforms, automatically replaces any :
delimiters in environment variables.
Consider the TransientFaultHandlingOptions
class:
public class TransientFaultHandlingOptions
{
public bool Enabled { get; set; }
public TimeSpan AutoRetryDelay { get; set; }
}
The following set
commands set the environment keys and values of SecretKey
and TransientFaultHandlingOptions
.
set SecretKey="Secret key from environment"
set TransientFaultHandlingOptions__Enabled="true"
set TransientFaultHandlingOptions__AutoRetryDelay="00:00:13"
These environment settings are only set in processes launched from the command window they were set in. They aren't read by web apps launched with Visual Studio.
With Visual Studio 2019 and later, you can specify environment variables using the Launch Profiles dialog.
The following setx commands can be used to set the environment keys and values on Windows. Unlike set
, setx
settings are persisted. /M
sets the variable in the system environment. If the /M
switch isn't used, a user environment variable is set.
setx SecretKey "Secret key from setx environment" /M
setx TransientFaultHandlingOptions__Enabled "true" /M
setx TransientFaultHandlingOptions__AutoRetryDelay "00:00:05" /M
To test that the preceding commands override any appsettings.json and appsettings.Environment
.json settings:
dotnet run
.To specify a prefix for environment variables, call AddEnvironmentVariables with a string:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.AddEnvironmentVariables(prefix: "CustomPrefix_");
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
In the preceding code:
config.AddEnvironmentVariables(prefix: "CustomPrefix_")
is added after the default configuration providers. For an example of ordering the configuration providers, see XML configuration provider.CustomPrefix_
prefix override the default configuration providers. This includes environment variables without the prefix.The prefix is stripped off when the configuration key-value pairs are read.
The default configuration loads environment variables and command-line arguments prefixed with DOTNET_
. The DOTNET_
prefix is used by .NET for host and app configuration, but not for user configuration.
For more information on host and app configuration, see .NET Generic Host.
The Configuration API has special processing rules for four connection string environment variables. These connection strings are involved in configuring Azure connection strings for the app environment. Environment variables with the prefixes shown in the table are loaded into the app with the default configuration or when no prefix is supplied to AddEnvironmentVariables
.
Connection string prefix | Provider |
---|---|
CUSTOMCONNSTR_ |
Custom provider |
MYSQLCONNSTR_ |
MySQL |
SQLAZURECONNSTR_ |
Azure SQL Database |
SQLCONNSTR_ |
SQL Server |
When an environment variable is discovered and loaded into configuration with any of the four prefixes shown in the table:
ConnectionStrings
).CUSTOMCONNSTR_
, which has no stated provider).Environment variable key | Converted configuration key | Provider configuration entry |
---|---|---|
CUSTOMCONNSTR_{KEY} |
ConnectionStrings:{KEY} |
Configuration entry not created. |
MYSQLCONNSTR_{KEY} |
ConnectionStrings:{KEY} |
Key: ConnectionStrings:{KEY}_ProviderName :Value: MySql.Data.MySqlClient |
SQLAZURECONNSTR_{KEY} |
ConnectionStrings:{KEY} |
Key: ConnectionStrings:{KEY}_ProviderName :Value: System.Data.SqlClient |
SQLCONNSTR_{KEY} |
ConnectionStrings:{KEY} |
Key: ConnectionStrings:{KEY}_ProviderName :Value: System.Data.SqlClient |
Important
Microsoft recommends that you use the most secure authentication flow available. If you're connecting to Azure SQL, Managed Identities for Azure resources is the recommended authentication method.
Environment variables set in launchSettings.json override those set in the system environment.
On Azure App Service, select New application setting on the Settings > Configuration page. Azure App Service application settings are:
Using the default configuration, the CommandLineConfigurationProvider loads configuration from command-line argument key-value pairs after the following configuration sources:
Environment
.json files.Development
environment.By default, configuration values set on the command line override configuration values set with all the other configuration providers.
With Visual Studio 2019 and later, you can specify command-line arguments using the Launch Profiles dialog.
The following command sets keys and values using =
:
dotnet run SecretKey="Secret key from command line"
The following command sets keys and values using /
:
dotnet run /SecretKey "Secret key set from forward slash"
The following command sets keys and values using --
:
dotnet run --SecretKey "Secret key set from double hyphen"
The key value:
=
, or the key must have a prefix of --
or /
when the value follows a space.=
is used. For example, SomeKey=
.Within the same command, don't mix command-line argument key-value pairs that use =
with key-value pairs that use a space.
The KeyPerFileConfigurationProvider uses a directory's files as configuration key-value pairs. The key is the file name. The value is the file's contents. The Key-per-file configuration provider is used in Docker hosting scenarios.
To activate key-per-file configuration, call the AddKeyPerFile extension method on an instance of ConfigurationBuilder. The directoryPath
to the files must be an absolute path.
Overloads permit specifying:
Action<KeyPerFileConfigurationSource>
delegate that configures the source.The double-underscore (__
) is used as a configuration key delimiter in file names. For example, the file name Logging__LogLevel__System
produces the configuration key Logging:LogLevel:System
.
Call ConfigureAppConfiguration
when building the host to specify the app's configuration:
.ConfigureAppConfiguration((_, configuration) =>
{
var path = Path.Combine(
Directory.GetCurrentDirectory(), "path/to/files");
configuration.AddKeyPerFile(directoryPath: path, optional: true);
})
The MemoryConfigurationProvider uses an in-memory collection as configuration key-value pairs.
The following code adds a memory collection to the configuration system:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.AddInMemoryCollection(
new Dictionary<string, string?>
{
["SecretKey"] = "Dictionary MyKey Value",
["TransientFaultHandlingOptions:Enabled"] = bool.TrueString,
["TransientFaultHandlingOptions:AutoRetryDelay"] = "00:00:07",
["Logging:LogLevel:Default"] = "Warning"
});
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
In the preceding code, MemoryConfigurationBuilderExtensions.AddInMemoryCollection(IConfigurationBuilder, IEnumerable<KeyValuePair<String,String>>) adds the memory provider after the default configuration providers. For an example of ordering the configuration providers, see XML configuration provider.
.NET feedback
.NET is an open source project. Select a link to provide feedback:
Training
Module
Externalize the configuration of an ASP.NET app by using an Azure key vault - Training
Learn how to use ConfigurationBuilder to dynamically configure an ASP.NET web app to retrieve secrets from an Azure key vault.