Instructor-led online courses in ASP.NET Core, ASP.NET MVC, and ASP.NET Design Patterns. Read more...
Instructor-led online courses in ASP.NET Core, ASP.NET MVC, and ASP.NET Design Patterns. Conducted by Bipin Joshi on weekends. More details are available here.

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 !!


Bipin Joshi is a software consultant, trainer, author and spiritual yoga mentor having 23+ years of experience in software development. He teaches online training courses in ASP.NET Core, ASP.NET MVC, and Design Patterns to individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 07 May 2018


Tags : ASP.NET ASP.NET Core MVC C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.