ASP.Net Core Configuration Settings
- docs.asp.net
- See also Environments for different sets of configuration
Web.config no longer exists, so connection strings and other settings must be stored in other files- json or xml or environmental variables.
ConfigurationBuilder
In a web application, it is done as part of Host.CreateDefaultBuilder(args), or, in .net 6, WebApplication.CreateBuilder(args)
The default order is (later ones override earlier ones):
- Environment variables
- appsettings.json in local directory
- app.{EnvironmentName}.settings.json in local directory
- Command line arguments
You can customise it in the Program.cs (net 1-5 code). NB CreateDefaultBuilder in core 3.1 (and WebApplication in net 6) automatically reads all the sources in order- there is no need to specify them manually unless you're doing something special.
Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(builder =>
{
//intended to set environment (DEV, PROD)
//optional, but if used, call this BEFORE ConfigureAppConfiguration
builder.AddEnvironmentVariables(); //if you've set DOTNET_ENVIRONMENT= "Production"
})
.ConfigureAppConfiguration((context, builder) =>
{
//optional, these are done automatically if you don't specify this...
builder.Sources.Clear(); //clear the default ones from CreateDefaultBuilder
builder.SetBasePath(Environment.CurrentDirectory);
builder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
builder.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true);
builder.AddEnvironmentVariables();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
In .net 6 there is a ConfigurationManager class, which looks similar, but adds the sources when you do builder.Add() ... builder.Build() is a no-op. This helps avoid scenarios when some config is needed for another (eg config in database).
Manual ConfigurationBuilder
In .net 6 consoles, there's no equivalent to WebApplication.CreateBuilder and we're stuck with the old Host.CreateDefaultBuilder(args). For consoles, it imposes an AddHostedService() using a type of IHostedService, which you have to implement. It's usually overkill, but you can get standard configuration out of it (and services too if required).
Most minimal: Install Microsoft.Extensions.Configuration.Json and Microsoft.Extensions.Configuration.Binder
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var settings = config.GetRequiredSection("Settings").Get<Settings>();
Hacky, but gets appsettings.[env].json just like asp, and you could build and get the services.
string environmentName = null;
var builder= Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
configuration = context.Configuration;
environmentName= context.HostingEnvironment.EnvironmentName;
services.AddTransient<IMyService, MyService>();
})
.Build();
var settings = configuration.GetRequiredSection("Settings").Get<Settings>();
var myService = builder.Services.GetService<IMyService>();
var runner = new Runner(environmentName, settings, myService);
runner.Run();
Using config settings
ConfigurationBuilder creates an IConfiguration object, a bag containing all your settings. The standard dependency injection will plug it into your constructors (including Startup.cs)
public RecordController(IConfiguration configuration)
{
_configuration = configuration;
}
You can access the values (including connection strings) as follows:
var connectionString = _configuration.GetConnectionString("DB");
//get values (with a default)
var myValue = _configuration.GetValue<string>("myValue", "myDefault");
//get sections with binding
var config = new ApiConfig();
_configuration.GetSection("ApiConfig").Bind(config);
//easier get sections
var config2 = _configuration.Get<ApiConfig>();
IOptions
You don't want to load the entire configuration into every class that just requires specific keys. The Options pattern breaks the config into small sections, with a simple poco class. This is registered with the DI (as services.Configure).
public void ConfigureServices(IServiceCollection services)
{
//load the configuration into a poco
services.Configure<MySettings>(Configuration.GetSection("a:b"));
}
The dependency injection can then load an IOptions<MySettings> into anything (IOptions is in Microsoft.Extensions.OptionsModel).
public void Service(IOptions<MySettings> settings)
{
var mysettings = settings.Value;
//do something with it
}