Meditation and Mindfulness for Software / IT Professionals. Conducted by Bipin Joshi in Thane. Read more...

Read the application's configuration in ASP.NET Core

As an ASP.NET developer you always used web.config to store and retrieve the application's configuration information. ASP.NET Core uses a different configuration system that is more flexible and powerful than before. In this article you will learn the basics of storing and retrieving the configuration information from JSON and XML files. You will also learn to use DI to inject this information into controllers.

Storing configuration in a JSON file

In ASP.NET Core the preferred format for storing the application's configuration is JSON. So, your application's configuration resides as a JSON in a physical file (there are in-memory ways too but we won't discuss them in this article). You can place this JSON file anywhere inside your application but the project's root folder (not same as web root) is a common location to store these files.

You can add an application configuration into your website using the Add New Item dialog :

By default, the configuration file name is appsettings.json but you can give any other name also.

Once added, you can store your application configuration into the file in JSON format. The following sample stores a few settings into the file :

{

  "SiteSettings": {
    "AdminEmail": "user@localhost",
    "UploadFolder": "Uploads",
    "Logo": "/images/logo.png",
    "Timeout" : 20
  }
}

The above JSON contains a key named SiteSettings that holds a set of hypothetical sub-keys viz. AdminEmail, UploadFolder, Logo and Timeout. This way you could have added any keys with any kind of nesting as required.

Reading the application configuration

Now that you have stored some application configuration, let's retrieve these values in code.

Open Startup.cs and remove the code that's already there in the constructor (I would like to show a bit simplified version of the code). Then write the following code :

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder();
    builder.SetBasePath(env.ContentRootPath);
    builder.AddJsonFile("appsettings.json", false, true);
    Configuration = builder.Build();
    string adminEmail = Configuration["SiteSettings:AdminEmail"];
}

Notice the code carefully. The first line creates a ConfigurationBuilder() object. It then sets the base path where configuration files are located. Here, we added the appsettings.json in the project's root folder and hence ContentRootPath has been used as the base path. The AddJsonFile() method specifies name of a JSON file containing the configuration information. The second parameter (false) indicates whether the file is optional or not. The value of false means the file must be present at the specified location. The third parameter indicates whether the configuration is to be reloaded if the file changes.

Then Build() method of the ConfigurationBuilder is called to load the configuration into IConfigurationRoot object. Notte that the Configuration is a property of the Startup class. Now you can read the configuration values. The simplest way to do so is to specify the colon ( : ) delimited nesting leading to the key to be accessed. Since we want to read the AdminEmail setting, we specified SiteSettings:AdminEmail. The returned string is assigned to a variable.

You could have also used Get() method of IConfigurationRoot as shown below :

string adminEmail = Configuration.GetValue<string>
("SiteSettings:AdminEmail");

Here, we used GetValue<T>() method and specified a key whose value is to be retrieved. The advantage of GetValue() comes where your values are not strings but other simple types such as integers (consider our Timeout key). Using the GetValue() method you can easily specify the type of the value you expect.

int timeout = Configuration.GetValue<int>
("SiteSettings:Timeout");

Storing configuration in multiple files

You can store the application's configuration in multiple files. You then need to load all of them and call Build() method as before. The following example shows how that can be done :

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder();
    builder.SetBasePath(env.ContentRootPath);
    builder.AddJsonFile("appsettings.json", false, true);
    builder.AddJsonFile("appsettings2.json", false, true);
    Configuration = builder.Build();

    string adminEmail1 = Configuration["SiteSettings:AdminEmail"];
    string adminEmail2 = Configuration["SiteSettings:AdminEmail2"];
}

The above code assumes that you have two configuration files - appsettings.json and appsettings2.json. The second file contains keys AdminEmail2, Timeout2 and so on. To load both the configuration files you call AddJsonFile() twice - one for each file. You can then access the individual keys as before. You you can see the Configuration object contains the sum total of the configuration from both the files.

What if the second configuration file redefines a same key as the first file (say AdminEmail is redefined in appsettings2.json)? In that case the value from the second file overwrites the earlier value. 

Storing database connection strings

It's quite common to store database connection strings in a configuration file. You can store them simply as a key as discussed earlier or you can use a simplified way designed specially for connection strings :

{
"ConnectionStrings": {
  "Northwind": "conn. str. here"
}

The above JSON consists of a ConnectionStrings section with a key - Northwind. The ConnectionStrings is a special section in that the Configuration object is aware of its purpose and hence treats it bit differently. To read the connection string shown above you would use the following code :

string connectionString = Configuration.
GetConnectionString("Northwind");

The GetConnectionString() method simply accepts the name of the connection string (Northwind in this case), looks for the ConnectionStrings section and returns the value if a match is found.

Passing the configuration information to controllers

In the preceding section you read the configuration information inside the Startup class itself. The Configuration is a property of the Startup class and you can access it anywhere within the class. What if you want to read the values inside the controllers? or some other class?

You can use Dependency Injection (DI) to inject the Configuration object in such cases. Let's see how that can be done.

Inside the ConfigureServices() method add the following line of code :

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<IConfigurationRoot>(Configuration);
}

Here, you registered the Configuration object with the DI framework. The AddSingleton() method ensures that only one instance of the object is used by all the requests.

Now, you can receive this injected object into a controller like this :

public HomeController(IConfigurationRoot config)
{
    string adminEmail = config["SiteSettings:AdminEmail"];
}

The constructor of the HomeController accepts the IConfigurationRoot object. You can then read the configuration settings as before.

Strongly typed configuration settings

In the preceding examples you used a string key to read a value. That means every time you need to type the whole key path to access its value. There is a better way to deal with this situation. You can fill a custom object with the configuration settings and then use the object wherever you wish to read the values. This way configuration settings can be accessed in a strongly typed manner. Let's see how this can be done.

Add a class - SiteSettings - to the project and write the following code in it.

public class SiteSettings
{
    public string AdminEmail { get; set; }
    public string UploadFolder { get; set; }
    public string Logo { get; set; }
    public int Timeout { get; set; }
}

The SiteSettings is a simple class with four properties namely AdminEmail, UploadFolder, Logo and Timeout. As you might have guessed these property names match with the key names used inside the configuration file.

Now, write the following code to the ConfigureServices() method :

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();
    services.Configure<SiteSettings>
   (Configuration.GetSection("SiteSettings"));
    services.AddMvc();
}

The AddOptions() method adds the DI support for injecting IOptions object. The Configure<T>() method registers SiteSettings with the DI framework. Notice that we used GetSection() method to retrieve just the SiteSettings key of the configuration file. This way other sections (if any) and keys won't be loaded.

Now, you can receive the injected settings in a controller as shown below :

public class HomeController : Controller
{
    SiteSettings options;

    public HomeController(IOptions<SiteSettings> options)
    {
        this.options = options.Value;
    }
}

The constructor of the HomeController accepts IOptions<T> object injected by the DI framework. You can access the SiteSettings object using the Value property. Once you have the SiteSettings object you can use its properties (such as options.AdminEmail) anywhere in the controller.

Storing configuration in XML files

So far you used JSON files to store configuration information. However, you can also use XML files if you so wish. Let's conclude this article with an example that illustrates just that.

Add an XML file to the project root folder named appsettings.xml and write the following markup into it :

<configuration>
  <SiteSettings>
    <AdminEmail>user@localhost</AdminEmail>
    <UploadFolder>Uploads</UploadFolder>
    <Logo>/images/logo.png</Logo>
    <Timeout>20</Timeout>
  </SiteSettings>
</configuration>

Here, the <configuration> root element (you can name it anything you wish) contains <SiteSettings> section. The SiteSettings section further contains four elements - <AdminEmail>, <UploadFolder>, <Logo> and <Timeout>.

To work with XML configuration you need to add this NuGet package - Microsoft.Extensions.Configuration.Xml. Once added you can modify the Startup constructor as shown below :

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder();
    builder.SetBasePath(env.ContentRootPath);
    builder.AddXmlFile("appsettings.xml", false, true);
    Configuration = builder.Build();
    string adminEmail1 = Configuration["SiteSettings:AdminEmail"];
}

Notice that the code uses AddXmlFile() method to add an XML file. Once loaded the configuration can be accessed in exactly same manner as before.

That's it for now! Keep coding!!




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

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 31 Mar 2017



Tags : ASP.NET ASP.NET Core .NET Framework C# Configuration