Configuration in .NET
Modern .NET applications often require flexible, environment-aware configurations. .NET’s built-in configuration system, powered by IConfiguration
, allows you to easily manage settings from multiple sources, including JSON files, environment variables, and more.
IConfiguration
Overview
The IConfiguration
interface in .NET provides a way to access key-value pairs from various configuration providers. It's commonly used to retrieve settings like connection strings, feature flags, and other application settings.
Configuration Providers
.NET's configuration system supports multiple providers. Here are a few common ones:
- appsettings.json: The most common provider. It's a JSON file where you can define your configuration settings.
- Environment Variables: Useful for injecting environment-specific settings, like in production environments.
- User Secrets: Ideal for local development where sensitive information (like API keys) needs to be kept outside of source control.
Using IConfiguration
IConfiguration
can be injected into classes, allowing you to access configurations from any source.
public class MyService
{
private readonly IConfiguration _configuration;
public MyService(IConfiguration configuration)
{
_configuration = configuration;
}
public void PrintSetting()
{
var setting = _configuration["MySetting"];
Console.WriteLine(setting);
}
}
This value could come from the appsettings.json
file, environment variables, or command-line arguments.
Example appsettings.json
file:
{
"MySetting": "Hello, World!"
}
appsettings.json
The appsettings.json
file is a standard way to manage configuration in .NET Core applications. The file uses a key-value structure to organize settings. You can also have environment-specific appsettings
files, like appsettings.Development.json
or appsettings.Production.json
.
Example appsettings.json
file:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=myServer;Database=myDB;User Id=myUser;Password=myPass;"
}
}
You can access the values in the appsettings.json
file by referencing their key paths. Note the use of :
to access the nested values.
var connectionString = _configuration["ConnectionStrings:DefaultConnection"];
Console.WriteLine(connectionString);
Connection strings are extremely common, so it has a special helper method to make it easier:
var connectionString = _configuration.GetConnectionString("DefaultConnection");
Console.WriteLine(connectionString);
Environment Variables
.NET's configuration system allows you to override values from appsettings.json
using environment variables, which is helpful when deploying applications across multiple environments.
To set an environment variable in a terminal window:
export ConnectionStrings__DefaultConnection="Server=prodServer;Database=prodDB;User Id=prodUser;Password=prodPass;"
Bind Complex Objects
You can bind sections of the configuration directly to strongly typed objects, simplifying access to complex configurations.
public class AppSettings
{
public string AppName { get; set; }
public string BaseUrl { get; set; }
}
Then, bind the configuration to the object:
var appSettings = new AppSettings();
_configuration.GetSection("AppSettings").Bind(appSettings);
You can also use the Get<T>
method to bind the configuration to a strongly typed object:
var appSettings = _configuration.GetSection("AppSettings").Get<AppSettings>();
Configuration in ASP.NET Core
In ASP.NET Core applications, the configuration system is integrated into the Generic Host. By default, appsettings.json
, environment variables, and command-line arguments are all supported without additional setup.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.AddCommandLine(args);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Because it's important to understand what .NET considers "default", you should browse source code for the CreateDefaultBuilder
method early and often to see how Microsoft "does things". You'd be surprised the number of times how I've been bitten by subtle behavior changes between default builders as the version of .NET has changed.