---
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"
Config
MyKey: @Configuration["MyKey"]
Position:Title: @Configuration["Position:Title"]
Position:Name: @Configuration["Position:Name"]
Logging:LogLevel:Default: @Configuration["Logging:LogLevel:Default"]
```
```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"
Config
@if (positionOptions != null)
{
Title: @positionOptions.Title
Name: @positionOptions.Name
}
```
```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` binds and returns the specified type. `ConfigurationBinder.Get` may be more convenient than using `ConfigurationBinder.Bind`.
The following code shows how to use `ConfigurationBinder.Get` 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();
}
}
```
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(option =>
{
var positionOptions = builder.Configuration.GetSection(PositionOptions.Position).Get();
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 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.