Configuration providers in .NET

Configuration in .NET is possible with configuration providers. There are several types of providers that 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:

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;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, configuration) =>
    {
        configuration.Sources.Clear();

        IHostEnvironment env = hostingContext.HostingEnvironment;

        configuration
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);

        IConfigurationRoot configurationRoot = configuration.Build();

        TransientFaultHandlingOptions options = new();
        configurationRoot.GetSection(nameof(TransientFaultHandlingOptions))
                         .Bind(options);

        Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
        Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
    })
    .Build();

// Application code should start here.

await host.RunAsync();

The preceding code:

  • Clears all existing configuration providers that were added by default in the CreateDefaultBuilder(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 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:

IConfigurationRoot configurationRoot = configuration.Build();

TransientFaultHandlingOptions options = new();
configurationRoot.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;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, configuration) =>
    {
        configuration.Sources.Clear();

        configuration
            .AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true)
            .AddXmlFile("repeating-example.xml", optional: true, reloadOnChange: true);

        configuration.AddEnvironmentVariables();

        if (args is { Length: > 0 })
        {
            configuration.AddCommandLine(args);
        }
    })
    .Build();

// Application code should start here.

await host.RunAsync();

The preceding code:

  • Clears all existing configuration providers that were added by default in the CreateDefaultBuilder(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.

<?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 = configuration.Build();

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;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, configuration) =>
    {
        configuration.Sources.Clear();

        IHostEnvironment env = hostingContext.HostingEnvironment;

        configuration
            .AddIniFile("appsettings.ini", optional: true, reloadOnChange: true)
            .AddIniFile($"appsettings.{env.EnvironmentName}.ini", true, true);
    })
    .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
    configuration.Build().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 : separator doesn't work with environment variable hierarchical keys on all platforms. The double underscore (__) is automatically replaced by a : and is supported by all platforms. For example, the : separator is not supported by Bash, but __ is.

The following set commands:

  • Set the environment keys and values of the preceding example on Windows.
  • Test the settings by changing them from their default values. The dotnet run command must be run in the project directory.
set SecretKey="Secret key from environment"
set TransientFaultHandlingOptions__Enabled="true"
set TransientFaultHandlingOptions__AutoRetryDelay="00:00:13"

dotnet run

The preceding environment settings:

  • Are only set in processes launched from the command window they were set in.
  • Won't be read by web apps launched with Visual Studio.

With Visual Studio 2019 version 16.10 preview 4 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

dotnet run

To test that the preceding commands override appsettings.json and appsettings.Environment.json:

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

Call AddEnvironmentVariables with a string to specify a prefix for environment variables:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, configuration) =>
        configuration.AddEnvironmentVariables(
            prefix: "CustomPrefix_"))
    .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 following commands test the custom prefix:

set CustomPrefix_SecretKey="Secret key with CustomPrefix_ environment"
set CustomPrefix_TransientFaultHandlingOptions__Enabled=true
set CustomPrefix_TransientFaultHandlingOptions__AutoRetryDelay=00:00:21

dotnet run

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.

On Azure App Service, select New application setting on the Settings > Configuration page. Azure App Service application settings are:

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

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

Environment variables set in launchSettings.json

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

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 version 16.10 preview 4 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;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((_, configuration) =>
        configuration.AddInMemoryCollection(
            new Dictionary<string, string>
            {
                ["SecretKey"] = "Dictionary MyKey Value",
                ["TransientFaultHandlingOptions:Enabled"] = bool.TrueString,
                ["TransientFaultHandlingOptions:AutoRetryDelay"] = "00:00:07",
                ["Logging:LogLevel:Default"] = "Warning"
            }))
    .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