ASP.NET Core Basics - Accessing Configuration Settings From Multiple Sources

Introduction

In older ASP.NET versions, we typically store the configuration settings in web.config and access it using ConfigurationManager Class. This worked well in the past, however, it is not good enough for modern technologies, like hosting in a cloud or a container-based solution. Moreover, storing the sensitive data in web.config poses the security risk if the file is check in to source control by accident.

In ASP.NET Core, Configuration API was introduced to access the key-value pair data from various sources in the order they are configured which allows you to access the configuration keys using Configuration Class regardless of where the keys are stored. If the same key value pair is stored in more than one places, the latest in order of precedence will overwrite the other values. Let’s dive into the demo to see how it works. 

Order of Precedence 

By default, ASP.NET Core version 2.0, the configuration providers order of precedence is hidden in Program.cs behind the method call CreateDefaultBuilder(). If you look at source code from GitHub, you will see that it loads the data in the following order.
  1. appsettings.json file
  2. appsettings.{env.EnvironmentName}.json file
  3. The local User Secrets File (local development environment only)
  4. Environment Variables
  5. Command Line Argument
  1. public static IWebHostBuilder CreateDefaultBuilder(string[] args) {  
  2.         var builder = new WebHostBuilder();  
  3.         if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey))) {  
  4.             builder.UseContentRoot(Directory.GetCurrentDirectory());  
  5.         }  
  6.         if (args != null) {  
  7.             builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());  
  8.         }  
  9.         builder.UseKestrel((builderContext, options) => {  
  10.             options.Configure(builderContext.Configuration.GetSection("Kestrel"));  
  11.         }).ConfigureAppConfiguration((hostingContext, config) => {  
  12.             var env = hostingContext.HostingEnvironment;  
  13.             config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddJsonFile($ "appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);  
  14.             if (env.IsDevelopment()) {  
  15.                 var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));  
  16.                 if (appAssembly != null) {  
  17.                     config.AddUserSecrets(appAssembly, optional: true);  
  18.                 }  
  19.             }  
  20.             config.AddEnvironmentVariables();  
  21.             if (args != null) {  
  22.                 config.AddCommandLine(args);  
  23.             }  
  24.         })  
In addition to that, you can also create custom providers by implementing IConfigurationSource interface and add it into the processing pipeline. Asp.net core also supports reading from xml file in addition to json file.

How it Works – Demo

In this Demo, we will see how to read and display the configuration key that is available from various sources and what value is displaying based on order of precedence. Launch the visual studio and create a new Asp.net Core Empty Web Application.

ASP.NET Core 

After the empty project is created, add the AppSettings.json item into the project.

ASP.NET Core 

Add the new key-value pair item called DemoConfigKey in the AppSettings.json and set the value as “Value from AppSettings.json”

 ASP.NET Core

In order to access the value from the configuration object, we need to use Startup constructor, as shown below.

ASP.NET Core 

After we added the Startup constructor with the parameter of type IConfiguration, we can store the injected IConfiguration object into a local variable and then use it anywhere within ConfigureServices() and Configure() and also we can access it from another controller via dependency injection passing the IConfiguration object in Controller Constructor.

In order to print the config value, I have just modified the default Configure method like below. This will print the value reading from configuration sources defined in the order.

ASP.NET Core 

When I run the application, you will see the result below reading from AppSettings.json.

ASP.NET Core
appsettings.{env.EnvironmentName}.json File 

This file is used to override the keys in appsettings.json with deployment environment specific settings. For example, a file named appsettings.production.json would contain values specific to production.

By default, the ASP.NET Core environment is a development environment. You can modify it in Visual Studio by changing it in Project Properties if needed.

ASP.NET Core 

Let’s add the environment specific AppSettings.Development.json file into the project.

ASP.NET Core 

Add the value for DemoConfigKey as “Value from AppSettings.Development.json”

ASP.NET Core 

Let’s run the application and see the result. We should get the value from AppSettings.Development.json by overwriting the value from AppSettings.json based on the order of precedence.

ASP.NET Core 
User Secrets

The User Secrets file is a JSON file stored on the local developer machine. This file is unencrypted and stored outside of the solution directory (under the user profile directory) and, therefore, is not checked into source control by accident. The user secrets file is used only for local development overrides like connecting to a local database server or development server API key values etc. These configuration values are only relevant to the local developer and any other developer/machine cannot access those values.

To add the UserSecrects.json file, right click on the project file and select Manage User Secrets.

ASP.NET Core 

Add the same key and set the different value as below.

ASP.NET Core 

Let's run the application and it should override all the other key values and put the value from Secrets.json 

ASP.NET Core 
Environment Variables 

Environment variables used mostly in container-based solutions like Docker Compose and Kubernetes. Docker allows environment variables to be configured in a Docker file using the ENV instruction. For example, 
  1. ENV DemoConfigKey - Value from Docker Environment Variable
See the Docker reference documentation for more details.

Command Line Variables 

Command line arguments allow you to modify the configuration keys when running your application without modifying any files using the command line syntax of key=value.

In this demo, we run the application in a command line window as below.

ASP.NET Core 

When running the application, you will see the result as below

ASP.NET Core 
Conclusion

ASP.NET Core allows you to have the same configuration key-value pair in multiple places and allows us to write the same code to access those values with the order of precedence regardless of its source. It also allows you to have multiple config files with a different set of keys and load them all in one configuration object. It is very useful when you want to split the configuration settings into a different file by module (Eg: All Database Related Key-Value Pairs in one file) or any other category that suitable for your application. For the Cloud-based solution, you should also consider using Azure Key vault for storing your sensitive secrets data.

As mentioned above, the default order of precedence was hidden behind the method CreateDefaultBuilder(args). If you want to create a custom configuration provider, you can do that by implementing IConfigurationSource Interface. I hope this article helps you to understand how configuration data is getting accessed at runtime from various sources.

Happy Coding!