Problem
How to read configuration settings from various sources and use them throughout your application.
Solution
Starting from the Empty Project from a previous post, add appsettings.json and appsettings.Development.json files in your project:
{
"Section1": {
"SettingA": "ValueA",
"SettingB": "ValueB"
},
"Section2": {
"SettingC": "ValueC"
}
}
{
"Section1": {
"SettingA": "Dev_ValueA"
},
"Section2": {
"SettingC": "Dev_ValueC"
}
}
Then, read configuration settings in the constructor for Startup
class:
public static IConfiguration Config { get; private set; }
public Startup(
IConfiguration config)
{
Config = config;
}
Then, add option services in ConfigureServicees()
method of Startup
class:
public void ConfigureServices(
IServiceCollection services)
{
services.AddOptions();
services.Configure(Config);
}
Finally, inject settings as IOptions
interface, where T
is your POCO:
public class HelloWorldMiddleware
{
private readonly RequestDelegate next;
private readonly AppSettings settings;
public HelloWorldMiddleware(
RequestDelegate next,
IOptions<AppSettings> options)
{
this.next = next;
this.settings = options.Value;
}
public async Task Invoke(HttpContext context)
{
var jsonSettings = JsonConvert.SerializeObject(this.settings);
await context.Response.WriteAsync(jsonSettings);
}
}
Running the sample application gives you following output:
Discussion
ASP.NET Core has a simple mechanism to read application settings from various sources like JSON file, Environment variables or even custom data sources. It is also simple to use the settings, thanks to Dependency Injection.
Although it seems like magic (how did your settings got loaded!) ASP.NET Core 2.0 hides the adding of configuration settings behind CreateDefaultBuilder()
method of WebHost
, in Program.cs. IConfiguration
is then added to the service container and is available in the rest of your application, we used this in Startup
to add options. To see this, replace the BuildWebHost()
method in Program.cs and run the program, you’ll get the same result:
public static IWebHost BuildWebHost(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, builder) =>
{
var env = context.HostingEnvironment;
builder.AddJsonFile("appsettings.json",
optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(
new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
builder.AddUserSecrets(appAssembly, optional: true);
}
}
builder.AddEnvironmentVariables();
if (args != null)
{
builder.AddCommandLine(args);
}
})
.UseStartup<Startup>()
.Build();
}
In the solution above, two JSON file sources are provided. The important thing to remember is that these sources are read sequentially and overwrite settings from the previous source. You could see this in the solution above, the output shows SettingB
’s value coming from first settings file whereas the other settings are being overwritten by the second settings file.
Note that a public static
property holds IConfiguration
instance so that it can be used throughout the application like:
var valueA = Config["Section1:SettingA"];
However, a better approach exists to read the settings, i.e., to read the settings into a typed POCO class and then inject it as dependency into middleware, controllers, etc. In the solution above, I’ve used the middleware from a previous post to demonstrate this pattern.
You can also have POCO classes for various sections in the settings file and read them using GetSection()
method on IConfiguration
:
services.Configure(Config.GetSection("Section1"));
It’s also possible to populate the settings in code using overload of IServiceCollection.Configure
that accepts strongly typed lambda:
services.Configure(options =>
{
options.Section1.SettingA = "SomeValue";
});