Configuration in ASP.NET Core

yawo
December 1, 2023

ASP.NET Core utilizes configuration providers to handle application configuration, drawing data from diverse sources like settings files (like appsettings.json), environment variables, Azure Key Vault, Azure App Configuration, command-line arguments, custom providers, directory files, and in-memory .NET objects.

Here is the default hierarchy (in read order) of Configuration Source with thei Configuration Provider:

!!!When the same key exists in several sources, only the last loaded key:value is considered.

A note about how to use User Secrets can be found here.

Our appsettings.json

Here is an example of appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "CustomSettings": {
    "Logging": true,
    "ProductionPrefix": "PROD__",
    "DevelopmentPrefix":  "DEV__"
  }
}

Getting the Configuration with the WebApplicationBuilder

Here are some ways to get the Configuration:

Using the WebApplicationBuilder in your Program.cs

var builder = WebApplication.CreateBuilder(args);

Console.WriteLine(builder.Configuration
    .GetSection("Logging")
    .GetSection("LogLevel")
    .GetSection("Default")
    .Value);
Console.WriteLine(builder.Configuration
    .GetSection("Logging")
    .GetSection("LogLevel")
    .GetValue<string>("Default"));
Console.WriteLine(builder
    .Configuration
    .GetValue<string>("Logging:LogLevel:Default"));

var app = builder.Build();

app.UseHttpsRedirection();

app.MapControllers();

app.Run();

Running the app shows "Information" printed 3 times:

To get a value, you can use GetValue<T> and specify the type of the value.

var value = builder.Configuration.GetValue<string>("SomeKey")
var boolValue = builder.Configuration.GetValue<bool>("SomeBooleanValueKey")

When there is an object/property structure, you can navigate using ":"

var value = builder.Configuration.GetValue<string>("Logging:LogLevel:Default")

You can also navigate using the GetSection method of the ConfigurationManager and :

var value = builder.Configuration
    .GetSection("Logging")
    .GetSection("LogLevel")
    .GetSection("Default")
    .Value

Getting the Configuration with the IConfiguration Interface

You can also inject the IConfiguration interface into your controller/classes to get the configuration. The following example uses the configuration interface to log some value to the terminal when GET /api/users is called

using Microsoft.AspNetCore.Mvc;

namespace ReadingConfiguration.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UsersController : ControllerBase
    {
        private readonly IConfiguration _configuration;

        public UsersController(IConfiguration configuration)
        {
            _configuration = configuration;          
        }

        [HttpGet]
        public IActionResult GetUsers()
        {
            var users = new[] { "John", "Doe", "David", "Pascal" };

            Console.WriteLine(_configuration
                .GetSection("Logging")
                .GetSection("LogLevel")
                .GetSection("Default")
                .Value);

            return Ok(users);
        }
    }
}

Binding the Configuration into a custom class with the IConfiguration Interface

You can also bin the Configuration into a custom class. Here it a custom class for our CustomSettings configuration:

public class CustomSettingsConfiguration
{
    public bool Logging { get; set; }

    public string ProductionPrefix { get; set; } = string.Empty;

    public string DevelopmentPrefix { get; set; } = string.Empty;

    public override string? ToString()
    {
        return $"Logging: {Logging}, ProductionPrefix: {ProductionPrefix}, DevelopmentPrefix: {DevelopmentPrefix} ";
    }
}

And then bind inside our controller/custom class. In the example below, the object key is CustomSettings

namespace ReadingConfiguration.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UsersController : ControllerBase
    {
        private readonly CustomSettingsConfiguration _customSettingsConfiguration;

        public UsersController(IConfiguration configuration)
        {
            _customSettingsConfiguration = new CustomSettingsConfiguration();
            // Binding
            configuration.GetSection("CustomSettings").Bind(_customSettingsConfiguration);
        }

        [HttpGet]
        public IActionResult GetUsers()
        {
            var users = new[] { "John", "Doe", "David", "Pascal" };

            Console.WriteLine(_customSettingsConfiguration.ToString());

            return Ok(users);
        }
    }
}

Configure using the Service Collection and the builder

We can also use configure this custom class using the Service Collection without the need to bind it inside the controller constructor.

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.Configure<CustomSettingsConfiguration>(builder.Configuration.GetSection("CustomSettings"));

And inject the IOptions inside the constructor

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace ReadingConfiguration.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class PostsController : ControllerBase
    {
        private readonly CustomSettingsConfiguration _customSettingsConfiguration;

        public PostsController(IOptions<CustomSettingsConfiguration> customSettingsConfiguration)
        {
            _customSettingsConfiguration = customSettingsConfiguration.Value;
        }

        [HttpGet("settings")]
        public IActionResult GetSettings()
        {
            return Ok(_customSettingsConfiguration.ToString());
        }
    }
}