I’ve been thinking and working with application configuration in ASP.NET applications for years, and its become a tool that I’m very comfortable using. I can add AppSettings, create configuration sections, and manage connectionstrings without thinking twice. However, there is a problem with the current ConfigurationManager and the XML-based config file offering in the .NET Framework: how do I get configuration entries from other sources into my application so that I don’t need to build my own configuration client and tools? I just want to continue using the standard syntax to access appsettings like this:
var serviceId = ConfigurationManager.AppSettings["ServiceID"];
Web.config and app.config have always been able to read external XML files, and assimilate their contents into .NET Configuration. In order to get application configuration from more sources, the ASP.NET team added the ConfigurationBuilder feature. The idea is simple: you add notation to your web.config or app.config for the ConfigurationBuildersSection and then you can load external configuration builders that will populate or modify the contents of a designated section. Let’s take a look at updating an application to get configuration from environment variables. Our standard configuration, stored in a web.config file, would look something like this:
To illustrate these configuration values, I wrote a simple application that output the values of appsettings to a web page. That page looks like this:
If we wanted to replace the appsettings for the ServiceID and ServiceKey, as well as point the defaultConnectionString at a new value provided by an environment variable, I can introduce a ConfigurationBuilder that will read the environment variables and replace these values in the ConfigurationManager that provides configuration data to my application. We can introduce the configuration builder by adding some simple markup to our configuration file:
The introduction of the configBuilders section with an entry for the configuration builder we want to use is simple markup that can be added to any configuration file. The catch is adding the configBuilders attribute to the sections that you want to apply the config builder to. In this case, we added it to the appSettings and connectionStrings elements. When the ConfigurationManager is first used and parses this file, it will load the configurationbuilder named Env in the configBuilders section and hand these sections to it for parsing. The Env entry points to a class called EnvironmentConfigBuilder whose source looks like:
That’s a pretty simple class that processes the XML handed to it, and replaces the values with any matching environment variable names. In a sample application that reports its appsettings values on a web page, I would see the following with appropriate values set in my production space:
Usage with Docker
This means that we can use this same application with the configuration builders attached and push settings into our container from outside. If we build this application with the Docker for Windows image microsoft/aspnet:4.7.1 we can then inject settings from outside the instance of the container. I’ll run my container with a command like the following:
docker run -d -p 80:80 -e ServiceID=Docker -e ServiceKey=DockerKey myapp
.. and if I browse to my running container on Windows, I’ll now see the following:
With no code changes, we’re able to inject settings into our application from an outside source that isn’t just another file. You can write configuration builders that read configuration from any source, and just update your web.config to consume that new configuration builder. In the weeks ahead, look for an official set of configuration builders from the ASP.NET team that supports JSON files, environment variables, and a number of other sources. I’ve even heard a request to write a configuration builder to read from an INI file.
Stay tuned, as we make using your applications in containers and on cloud services even easier.