How to read configuration values in ASP.NET Core
21 Aug 2020 #tutorial #asp.net #csharpLet’s see how to read and overwrite configuration values with ASP.NET Core 6.0 using the Options pattern.
To read configuration values following the Options pattern, add a new section in the appsetttings.json file, create a matching class, and register it into the dependencies container using the Configure() method.
Let’s see how to use, step by step, the Options pattern to read configuration values.
1. Change the appsettings.json file
After creating a new ASP.NET Core API project with Visual Studio or the dotnet tool from a terminal, let’s add in the appsettings.json
file the values we want to configure on a new JSON object.
Let’s add a couple of configuration values inside a new MySettings
object in our appsettings.json
file like this,
{
"MySettings": {
"AString": "Hello, there!",
"ABoolean": true,
"AnInteger": 1,
"AnArray": ["hello", ",", "there", "!"]
}
}
Inside the appsettings.json
file, we can use booleans, integers, and arrays, not only strings.
2. Create and bind a configuration class
Then, let’s create a matching configuration class for our configuration section in the appsettings.json
file.
We should name our configuration class after our section name and its properties after the keys inside our section.
This is the configuration class for our MySettings
section,
public class MySettings
{
public string AString { get; set; }
public bool ABoolean { get; set; }
public int AnInteger { get; set; }
public string[] AnArray { get; set; }
}
Next, let’s bind our configuration class to our custom section and register it into the built-in dependencies container. In our Program.cs
class, let’s use the Configure()
method for that,
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var mySettingsSection = builder.Configuration.GetSection("MySettings");
builder.Services.Configure<MySettings>(mySettingsSection);
// ^^^^^
var app = builder.Build();
app.MapControllers();
app.Run();
As an alternative, we can use GetRequiredSection()
instead. It throws an InvalidOperationException
if we forget to add the configuration section in our appsettings.json
file.
3. Use sections and subsections
Let’s use sections and subsections to group our configuration values on appsettings.json
files.
Now let’s say MySettings
is inside another section: AllMyCoolSettings
. We need a new AllMyCoolSettings
class containing a MySettings
property like this,
public class AllMyCoolSettings
{
public MySettings MySettings { get; set; }
// ^^^^^
}
Then, in the Configure()
method, we separate the section and subsection names using a colon, :
, like this,
var mySettings = builder.Configuration.GetSection("AllMyCoolSettings:MySettings");
// ^^^^^
builder.services.Configure<MySettings>(mySettings);
4. Inject an IOptions interface
To use these configuration values, let’s add an IOptions<T>
parameter in the constructor of our service or controller.
Let’s create a simple controller that prints one of our configured values,
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly MySettings _mySettings;
public ValuesController(
IOptions<MySettings> mySettingsOptions)
// ^^^^^
{
_mySettings = mySettingsOptions.Value;
// ^^^^^
}
[HttpGet]
public string Get()
{
return _mySettings.ASetting;
// ^^^^^
}
}
The IOptions<T>
interface has a property Value
. It holds an instance of our configuration class with the parsed values from the appsettings.json
file.
In our controller we use the injected MySettings
like any other object instance.
By default, if we forget to add a configuration value in the appsettings.json
file, ASP.NET Core doesn’t throw any exception. Instead, ASP.NET Core initializes the configuration class to its default values.
That’s why it’s a good idea to always validate for missing configuration values inside constructors.
For unit testing, let’s use the method Options.Create()
with an instance of the MySettings
class we want to use. We don’t need a stub or mock for that!
5. Use separate configuration files per environment
Let’s separate our configuration values into different configuration files per environment.
By default, ASP.NET Core creates two JSON files: appsettings.json
and appsettings.Development.json
. But we could have other configuration files, too.
If ASP.NET Core doesn’t find a value in an environment-specific file, it reads the default appsettings.json
file instead.
ASP.NET Core reads the current environment from the ASPNETCORE_ENVIRONMENT
environment variable.
On a development machine, we can use the launchSettings.json
file to set environment variables.
For example, let’s override one configuration value using an environment variable in our launchSettings.json
file,
{
"<YourSolutionName>": {
"commandName": "Project",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
// ^^^^^
"MySettings__AString": "This value comes from an environment variable"
// ^^^^^
}
}
}
}
By default, ASP.NET Core reads configuration values from environment variables, too.
Environment variables have a higher precedence than JSON files.
For example, if we set an environment variable MySettings__AString
, ASP.NET Core will use that value instead of the one on the appsettings.json
file.
Notice that the separator for sections and subsections inside environment variables is a double undescore, __
.
6. Embrace PostConfigure
After registering our configuration classes, we can override their values using the PostConfigure()
method.
I used PostConfigure()
when refactoring a legacy application. I grouped related values in the appsetting.json
file into sections. But I couldn’t rename the existing environment variables to match the new names. I did something like this instead,
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var mySettingsSection = builder.Configuration.GetSection("MySettings");
builder.Services.Configure<MySettings>();
builder.Services.PostConfigure<MySettings>(options =>
// ^^^^^
{
var anOldSetting = Environment.GetEnvironmentVariable("AnOldSettingName");
// ^^^^^
if (!string.IsNullOrEmpty(anOldSetting))
{
options.AString = anOldSetting;
// ^^^^^
}
});
var app = builder.Build();
app.MapControllers();
app.Run();
Conclusion
Voilà! That’s how to read configuration values with ASP.NET Core 6.0. Apart from the IOptions
interface we used here, ASP.NET Core has IOptionSnapshot
and IOptionsMonitor
. Also, we can read values from INI files, XML files, or Azure Key Vault.
In the days of the old ASP.NET framework, we had a ConfigurationManager
class and a web.config
file to read configuration values. Those days are gone! We have JSON files now.
For more ASP.NET Core content, check how to create a caching layer, how to create a CRUD API with Insight.Database, and how to use background services with Hangfire.
Happy coding!