Click here to Skip to main content
13,703,000 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

6.7K views
7 bookmarked
Posted 21 Nov 2017
Licenced Ms-PL

Modern Configuration for ASP.NET 4.7.1 with ConfigurationBuilders

, 21 Nov 2017
Rate this:
Please Sign up or sign in to vote.
Modern configuration for ASP.NET 4.7.1 with ConfigurationBuilders

I've been thinking and working with application configuration in ASP.NET applications for years, and it's 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"];

Introducing ConfigurationBuilders

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:

<configuration>
	<appSettings>
		<add key="ServiceID" value="JeffsService" />
		<add key="ServiceKey" value="TopSecret" />
	</appSettings>
	
	<connectionStrings>
		<add name="default" connectionString="Data Source=mydb.db" />
	</connectionStrings>

...

</configuration>

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:

Outputting Configuration from Config File

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:

<configuration>
  
  <configSections>
		<section name="configBuilders" 



       type="System.Configuration.ConfigurationBuildersSection, 
       System.Configuration, Version=4.0.0.0, Culture=neutral, 
       PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
	</configSections>

  <configBuilders>
		<builders>
			<add name="Env" 



         type="MyConfigBuilders.EnvironmentConfigBuilder, MyConfigBuilders" />
		</builders>
	</configBuilders>
  
	<appSettings configBuilders="Env">
		<add key="ServiceID" value="JeffsService" />
		<add key="ServiceKey" value="TopSecret" />
	</appSettings>
 
	<connectionStrings configBuilders="Env">
		<add name="default" connectionString="Data Source=mydb.db" />
	</connectionStrings>

...

</configuration>

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:

public class EnvironmentConfigBuilder : ConfigurationBuilder
	{
		private readonly IDictionary _EnvVars;

		public EnvironmentConfigBuilder()
		{
			_EnvVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
			if (_EnvVars.Count == 0) _EnvVars = Environment.GetEnvironmentVariables();

			Debug.WriteLine(_EnvVars.Count);
		}

		public override XmlNode ProcessRawXml(XmlNode rawXml)
		{
			foreach (DictionaryEntry envVar in _EnvVars)
			{
				var pair = (Key: envVar.Key.ToString(), Value: envVar.Value.ToString());

				if (rawXml.HasChildNodes 
					&& rawXml.SelectSingleNode($"add[@key='{pair.Key}']") != null)
				{
					rawXml.SelectSingleNode($"add[@key='{pair.Key}']")
						.Attributes["value"].Value = pair.Value;
				}
			}

			return rawXml;			
		}

		public override ConfigurationSection ProcessConfigurationSection(
			ConfigurationSection configSection)
		{
			return base.ProcessConfigurationSection(configSection);
		}
	}
}

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:

Settings Overridden from Environment Variables

Settings Overridden from Environment Variables in Production

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:

AppSettings Overridden in a Docker Container

Summary

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.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Jeffrey T. Fritz
Program Manager
United States United States
Jeffrey is a software developer coach, architect, and speaker in the Microsoft.Net community. He currently works as a program manager for the Microsoft .NET Developer Outreach group. He has delivered training videos on Pluralsight, WintellectNow, and on YouTube. Jeffrey makes regular appearances delivering keynotes, workshops, and breakout sessions at conferences such as TechEd, Ignite, DevIntersection, CodeStock, FalafelCon, VSLive as well as user group meetings in an effort to grow the next generation of software developers.

You may also be interested in...

Comments and Discussions

 
QuestionProcessConfigurationSection in ConfigurationBuilder .net 4.7.1 Pin
Reza71121-Mar-18 2:09
memberReza71121-Mar-18 2:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04-2016 | 2.8.180920.1 | Last Updated 21 Nov 2017
Article Copyright 2017 by Jeffrey T. Fritz
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid