You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Blazor/Documentation/docusaurus/docs/configuration.md

9.9 KiB

sidebar_position title
13 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:

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:

{
  "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:

@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>
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:

"Position": {
	"Title": "Editor",
    "Name": "Joe Smith"
}

Create the following PositionOptions class:

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.
@page "/config"
<h3>Config</h3>

@if (positionOptions != null)
{
    <div>
        <div>Title: @positionOptions.Title</div>
        <div>Name: @positionOptions.Name</div>
    </div>
}
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:

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:

...

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:

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.
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.

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.