static void

ASP.Net Core Configuration Settings

Web.config no longer exists, so connection strings and other settings must be stored in other files- json or xml or environmental variables.

ConfigurationBuilder

You can manually new a ConfigurationBuilder directly (without the DI/logging of Host)

var builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
IConfigurationRoot config = builder.Build();
string value = config["Key"]; // get a value

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

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.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    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((contextbuilder) =>
        {
            //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"optionaltruereloadOnChangetrue);
            builder.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json"optionaltruereloadOnChangetrue);
            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).

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)

private readonly IConfiguration _configuration;
public RecordController(IConfiguration configuration)
{
    _configuration = configuration;
}

You can access the values (including connection strings) as follows:

//connection strings - "ConnectionStrings": {"DB": "Data Source=..."}
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
}