Configuration providers in .NET

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.

File configuration provider

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.

JSON configuration provider

The JsonConfigurationProvider class loads configuration from a JSON file. Install the Microsoft.Extensions.Configuration.Json NuGet package.

Overloads can specify:

  • Whether the file is optional.
  • Whether the configuration is reloaded if the file changes.

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:

  • Clears all existing configuration providers that were added by default in the CreateApplicationBuilder(String[]) method.
  • Configures the JSON configuration provider to load the appsettings.json and appsettings.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

XML configuration provider

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:

  • Clears all existing configuration providers that were added by default in the CreateApplicationBuilder(String[]) method.
  • Configures the XML configuration provider to load the appsettings.xml and repeating-example.xml files with the following options:
    • optional: true: The file is optional.
    • reloadOnChange: true: The file is reloaded when changes are saved.
  • Configures the environment variables configuration provider.
  • Configures the command-line configuration provider if the given 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

INI configuration provider

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

Environment variable configuration provider

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.

Launch Profiles dialog showing environment variables

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:

  • With Visual Studio: Exit and restart Visual Studio.
  • With the CLI: Start a new command window and enter dotnet run.

Prefixes

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.
  • Environment variables set with the 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.

Connection string prefixes

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:

  • The configuration key is created by removing the environment variable prefix and adding a configuration key section (ConnectionStrings).
  • A new configuration key-value pair is created that represents the database connection provider (except for 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

Environment variables set in launchSettings.json override those set in the system environment.

Azure App Service settings

On Azure App Service, select Add on the Settings > Environment variables page. Azure App Service application settings are:

  • Encrypted at rest and transmitted over an encrypted channel.
  • Exposed as environment variables.

Command-line configuration provider

Using the default configuration, the CommandLineConfigurationProvider loads configuration from command-line argument key-value pairs after the following configuration sources:

  • appsettings.json and appsettings.Environment.json files.
  • App secrets (Secret Manager) in the Development environment.
  • Environment variables.

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.

Launch Profiles dialog showing command-line arguments

Command-line arguments

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:

  • Must follow =, or the key must have a prefix of -- or / when the value follows a space.
  • Isn't required if = 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.

Key-per-file configuration provider

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:

  • An Action<KeyPerFileConfigurationSource> delegate that configures the source.
  • Whether the directory is optional and the path to the directory.

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);
})

Memory configuration provider

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.

See also