Store ASP.NET Core Application Configuration in Multiple Files
ASP.NET Core applications typically store configuration information in
appsettings.json file. Although this default arrangement works in many
situations, at times you need to store your application configuration in
multiple physical files. Luckily, storing configuration in multiple files is not
a big deal since ASP.NET Core by design supports this feature. However, you need
to be aware of a few things involved in the process. This article discusses just
that.
Default way of using application configuration
By default ASP.NET Core assumes that your application configuration is stored
in appsettings.json file, typically placed in the project root folder. For
example, consider the following appsettings.json file :

The configuration consists of a custom section - WebsiteSettings - that
defines two keys - Title and Email.
To get hold of this configuration in your startup code you would use Startup
constructor as shown below :
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration config)
{
this.Configuration = config;
}
}
The Startup constructor now takes a parameter of type IConfiguration. You can
store the injected IConfiguration object in a local variable and then use it
anywhere within ConfigureServices() and Configure().
You can also inject IConfiguration in controllers as shown below :
public class HomeController : Controller
{
IConfiguration config = null;
public HomeController(IConfiguration config)
{
this.config = config;
}
}
This code looks similar to the Startup constructor but it's from
HomeController. Once you get an object of IConfiguration you can use it anywhere
inside the controller. For example, you can read the application configuration
in any action as shown below :
public IActionResult Index()
{
ViewData["Title"] = config.GetValue<string>
("WebsiteSettings:Title");
ViewData["Email"] = config.GetValue<string>
("WebsiteSettings:Email");
return View();
}
Here, we use GetValue() method of IConfiguration to retrieve a string keys
named Title and Email from under WebsiteSettings section. For the sake of
testing you can output these ViewData keys on the Index view :
<h1>Welcome!!!</h1>
<h2>@ViewData["Title"]</h2>
<h2>@ViewData["Email"] </h2>
And here is the output in the browser :

So far so good.
Storing configuration in multiple files
Now, let's store application configuration in multiple files. As an example
we will use three files namely appsettings.json, moresettings.json and
moresettings.xml.
The appsettings.json is exactly as before. The other JSON file -
moresettings.json - contains the following configuration :

This piece of configuration also has WebsiteSettings section. It redefines
the Title and Email keys and also adds a new key named Theme. You can also add
more sections and keys as per your requirement.
The moresettings.xml is shown below :

Notice this markup carefully. This markup also defines WebSiteSettings
section and three settings - Title, Email, and Timeout.
We are redefining Title and Email keys in these files just to see what
happens when keys are redefined across multiple configuration files.
In this example we have stored application configuration in multiple files.
The ASP.NET Core framework is unaware of this fact and hence injected
IConfiguration still contains configuration only from the default configuration
file - appsettings.json.
To load and inject the configuration settings from all the files you need to
modify the Startup constructor like this :
public IConfiguration Configuration { get; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder();
builder.SetBasePath(env.ContentRootPath);
builder.AddJsonFile("appsettings.json", false, true);
builder.AddJsonFile("moresettings.json", false, true);
builder.AddXmlFile("moresettings.xml", false, true);
Configuration = builder.Build();
}
This code creates ConfigurationBuilder and set's the base folder path where
configuration files are stored. It then adds two JSON files and one XML file
using AddJsonFile() and AddXmlFile() respectively. The code then calls Build()
method of ConfigurationBuilder and generates IConfiguration object containing
the configuration from all the three files.
Since we created IConfiguration ourselves, we also need to register it with
the DI framework :
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IConfiguration>(Configuration);
}
We do this using AddSingleton() method inside the configureServices().
You can now inject this IConfiguration in the HomeController as before and
also read the configuration settings.
If you run the application, you should see something like this :

Did you notice how values are merged? The Title and Email keys from
appsettings.json are overridden by the ones from moresettings.xml. That's
because you added moresettings.xml after appsettings.json and moresettings.json.
Further, Theme key from moresettings.json and Timeout key from moresettings.xml
have been added to the resultant IConfiguration object.
Supplying the default configuration to ASP.NET Core
Although the above example works as expected you need to register your own
IConfiguration with the DI container. If you don't do this, HomeController won't
get the desired configuration settings. Wouldn't it be a good idea to supply our
configuration from multiple files as the default configuration to our
application. This way you neither need to build the IConfiguration in Startup()
nor do you need to register IConfiguration in the ConfigurationServices()
method.
Let's see how this can be accomplished. First of all, comment out
Configuration property, Startup constructor and also the AddSingleton() call
from the ConfigureServices(). Then open Program.cs file and modify the
BuildWebHost() as shown below :
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((webHostBuilderContext,
configurationbuilder) =>
{
var env = webHostBuilderContext.HostingEnvironment;
configurationbuilder.SetBasePath(env.ContentRootPath);
configurationbuilder.AddJsonFile("appsettings.json", false, true);
configurationbuilder.AddJsonFile("moresettings.json", false, true);
configurationbuilder.AddXmlFile("moresettings.xml", false, true);
configurationbuilder.AddEnvironmentVariables();
})
.UseStartup<Startup>()
.Build();
}
Notice the code marked in bold letters. We wire the ConfigureAppConfiguration()
method that loads the configuration from the three files and prepares the
underlying ConfigurationBuilder object. This way before the control reaches
Startup() you have the configuration from all the three files loaded in
IConfiguration.
If you run the application the result would be similar to the previous run.
That's it for now! Keep coding !!