---
sidebar_position: 13
title: Configuration
---

Configuration in ASP.NET Core is done using one or more configuration providers.
Configuration providers read configuration data from key-value pairs using a variety of configuration sources:

* Settings files, such as `appsettings.json`
* Environment Variables
* Azure Key Vault
* Azure App Setup
* Command line arguments
* Custom, installed or created providers
* Directory files
* .NET objects in memory

:::caution
Configuration and settings files in a Blazor WebAssembly app are visible to users. Don't store application secrets, credentials, or other sensitive data in a WebAssembly application's configuration or files.
:::

## Default configuration

ASP.NET Core web apps created with dotnet new or Visual Studio generate the following code:

```csharp
public static async Task Main(string[] args)
{
// highlight-next-line
	var builder = WebApplication.CreateBuilder(args);
	
	...
```

`CreateBuilder` provides the default application configuration in the following order:

* `ChainedConfigurationProvider`: adds an existing `IConfiguration` as a source. In the case of default configuration, adds the host configuration and sets it as the first source of the application configuration.
* `appsettings.json` using default JSON provider.
* appsettings.`Environment`.json using the default JSON provider. For example, appsettings.**Production**.json and appsettings.**Development**.json.
* Application secrets when the application is running in the `Development` environment.
* Environment variables using the environment variables configuration provider.
* Command line arguments using the command line configuration provider.

Configuration providers added later override previous key settings.
For example, if `MyKey` is defined in both `appsettings.json` and the environment, the environment value is used.
Using the default configuration providers, the command-line configuration provider overrides all other providers.

## appsettings.json

Consider the following `appsettings.json` file:

```json title="appsettings.json"
{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey":  "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}
```

The following code displays several of the previous configuration parameters:

```html title="Config.razor"
@page "/config"
<h3>Config</h3>

<div>
    <div>MyKey: @Configuration["MyKey"]</div>
    <div>Position:Title: @Configuration["Position:Title"]</div>
    <div>Position:Name: @Configuration["Position:Name"]</div>
    <div>Logging:LogLevel:Default: @Configuration["Logging:LogLevel:Default"]</div>
</div>
```

```csharp title="Config.razor.cs"
using Microsoft.Extensions.Configuration;

public partial class Config
{
	[Inject] 
	public IConfiguration Configuration { get; set; }
}
```

The default `JsonConfigurationProvider` configuration loads in the following order:

* appsettings.json
* appsettings.`Environment`.json: for example, appsettings.**Production**.json and appsettings.**Development**.json. The environment version of the file is loaded from `IHostingEnvironment.EnvironmentName`.

Values ​​in appsettings.`Environment`.json override keys in appsettings.json. For example, by default:

* In development, the appsettings.**Development**.json file overrides the values ​​found in appsettings.json.
* In production, the appsettings.**Production**.json file overrides the values ​​found in appsettings.json. For example, when deploying the application to Azure.

If a configuration value must be guaranteed, use `GetValue`. The preceding example only reads strings and does not support a default value.

Using the default configuration of appsettings.json and appsettings.`Environment`.json. files are enabled with `reloadOnChange: true`.
Changes made to the appsettings.json and appsettings.`Environment`.json files after the application starts are read by the JSON configuration provider.

## Bind hierarchical configuration data using the options model

The recommended way to read related configuration values is using the options pattern. For example, to read the following configuration values:

```json title="appsettings.json"
"Position": {
	"Title": "Editor",
    "Name": "Joe Smith"
}
```

Create the following `PositionOptions` class:

```csharp title="PositionOptions.cs"
public class PositionOptions
{
    public const string Position = "Position";

    public string Title { get; set; }
    public string Name { get; set; }
}
```

An option class:

* Must be non-abstract with a public parameterless constructor.
* All public read/write properties of the type are bound.
* The fields are not linked. In the preceding code, `Position` is not bound. The `Position` property is used so that the "Position" string does not have to be hard-coded into the application when binding the class to a configuration provider.

The following code:

* Calls `ConfigurationBinder.Bind` to bind the `PositionOptions` class to the `Position` section.
* Displays `Position` configuration data.

```html title="Config.razor"
@page "/config"
<h3>Config</h3>

@if (positionOptions != null)
{
    <div>
        <div>Title: @positionOptions.Title</div>
        <div>Name: @positionOptions.Name</div>
    </div>
}
```

```csharp title="Config.razor.cs"
public partial class Config
{
	[Inject] 
	public IConfiguration Configuration { get; set; }

	private PositionOptions positionOptions;

	protected override void OnInitialized()
	{
		base.OnInitialized();
		
		positionOptions = new PositionOptions();
		Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);
	}
}
```

In the preceding code, by default, changes made to the JSON configuration file after the application starts are read.

`ConfigurationBinder.Get<T>` binds and returns the specified type. `ConfigurationBinder.Get<T>` may be more convenient than using `ConfigurationBinder.Bind`.
The following code shows how to use `ConfigurationBinder.Get<T>` with the `PositionOptions` class:

```csharp title="Config.razor.cs"
public partial class Config
{
	[Inject] 
	public IConfiguration Configuration { get; set; }

	private PositionOptions positionOptions;

	protected override void OnInitialized()
	{
		base.OnInitialized();
		
		positionOptions = Configuration.GetSection(PositionOptions.Position).Get<PositionOptions>();
	}
}
```

Another approach to using the options pattern is to bind the section and add it to the dependency injection service container.
In the following code, `PositionOptions` is added to the service container with `Configure` and bound to the configuration:

```csharp title="Program.cs"
...

builder.Services.Configure<PositionOptions>(option =>
{
	var positionOptions = builder.Configuration.GetSection(PositionOptions.Position).Get<PositionOptions>();

	option.Name = positionOptions.Name;
	option.Title = positionOptions.Title;
});

...
```

Using the previous code, the following code reads the position options:

```csharp title="Config.razor.cs"
public partial class Config
{
	[Inject] 
	public IConfiguration Configuration { get; set; }

	[Inject] 
	public IOptions<PositionOptions> OptionsPositionOptions { get; set; }

	private PositionOptions positionOptions;
	
	protected override void OnInitialized()
	{
		base.OnInitialized();

		positionOptions = OptionsPositionOptions.Value;
	}
}
```

## User Security and Secrets

Instructions for configuration data:

* Never store passwords or other sensitive data in configuration provider code or plain text configuration files. The Secret Manager tool can be used to store secrets in development.
* Do not use any production secrets in development or test environments.
* Specify secrets outside of the project so they can't be inadvertently committed to a source code repository.
By default, the user secrets configuration source is listed after the JSON configuration sources.
Therefore, user secrets keys take precedence over keys in appsettings.json and appsettings.`Environment`.json.

## Environment Variables

Using the default configuration, the `EnvironmentVariablesConfigurationProvider` loads the configuration from environment variable key-value pairs after reading the `appsettings.json` file, appsettings.`Environment`.json and secrets of the user.
Therefore, key values ​​read from the environment override values ​​read from `appsettings.json`, appsettings.`Environment`.json and user secrets.

The `:` separator does not work with hierarchical environment variable keys on all platforms. `__`, the double underscore, is:

* Supported by all platforms. For example, the `:` separator is not supported by `Bash`, but `__` is.
* Automatically replaced by a `:`

The following `set` commands:

* Set the environment keys and values ​​from the previous example to Windows.
* Test the settings during use. The dotnet run command should be run in the project directory.

```shell
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run
```

Previous environment settings:

* Are only defined in processes launched from the command window in which they were defined.
* Will not be read by browsers launched with Visual Studio.

The following `setx` commands can be used to set environment keys and values on Windows.
Unlike `set`, the `setx` parameters are preserved. `/M` sets the variable in the system environment.
If the `/M` switch is not used, a user environment variable is set.

```shell
setx MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M
```

To verify that the previous commands override `appsettings.json` and appsettings.`Environment`.json:

* with Visual Studio: quit and restart Visual Studio.
* With CLI interface: start a new command window and enter `dotnet run`.

One of the great interest of environment variables and the use of it with Docker.
