Multiple deployment configs in one config file with ACL

By | 2014-09-30

Most projects that is deployed into production require some kind of config change upon deployment. Often it is the connection string that varies, but it can be any number of custom settings. Forgetting to change the config file when deploying, or forgetting to change config back on your dev machine after deploying can have disastrous consequences.

Back in 2005 Scott Guthrie suggested keeping separate config files and adding pre build event handler to copy correct file into place. Scott Hanselman suggested a similar approach. Visual Studio 2010 has a XSLT-based debug/release transformation upon deploy, but it has its own set of problems.

Though these solutions are fine and will do the job they do have a couple of drawbacks.

  • They still require you to remember to switch build profile.
    Failing to do so may end in prod system working on dev database, or development happening directly on prod system. On some projects this is not such a big thing, while on others it would be flat out catastrophic. If you are in the latter group you know what I’m talking about.
  • You need to maintain multiple copies of your web.config/app.config.
    Every time you add a reference or add a NuGet package that alters your config you need to manually update the other config files.

So I suggest an alternative approach. By adding a custom config section which contains the necessary configuration we can keep multiple configurations in one config file. By adding ACL (Access Control Lst) to this we can make sure it never runs on the wrong machine We’ll process the directive early on and inject the config into the usual places (connectionStrings and appSettings) so the rest of the app will work as expected without any change required.

The configuration

A sample config file might look something like this:

 

What we have done here is to add the “sectionGroup” inside the “configSections” tags. If your config file doesn’t contain the “configSections” tags they must be added too.

Note that the first parameter in “section type” is the class where our config is located, the second parameter is the assembly (class, assembly). You need to modify the second parameter to match the assembly name of your project (or simply follow the instructions in “Summary”).

Some explanation

First of all we’ll need to define the section type, shown as “<section name=devtype=Tedd.AclConfig.TargetSystemConfigSection/>” in the config file. We start at this level so that we allow you to add any number of configurations to the system simply by adding sections in your config file.

  1. Add reference to “System.Configuration” in your project.
  2. Add a class named “TargetSystemConfigSection” under the namespace “Tedd.AclConfig” and have it inherit “ConfigurationSection”.
  3. Define 3 sections: connectionStrings, appSettings and allowedComputers.
    Note! If you want any attributes directly onto the tag (ie. <dev name=”Development”>…) then simply add a ConfigurationProperty of type string, int, bool or whatever you need.
  4. For each section define a section collection.
  5. For each collection define a config element.
  6. A class “TargetConfigLoader” is used to read config, check ACL and copy appSettings/connectionStrings.
  7. We need to call TargetConfigLoader.InitConfig() first thing when application starts. This can be done by adding a line to the startup of your application. Different project types have different startup codes.
    • Console/WinForms/WPF: As first line in “Main” function in Program.cs.
    • Web project: As first line in “Application_Start()” in Global.asax. If your project doesn’t have a global.asax-file you need to add it first.

 

The code

 

Summary

To sum it all up here is a quick step-by-step guide to get up and running:

  1. Add a new class project to your solution, name it “Tedd.AclConfig”.
  2. Add reference to “System.Configuration” in “Tedd.AclConfig”.
  3. In “Tedd.AclConfig”, create a new class file named “TargetConfig”.
  4. Empty the new class file and copy the CS-code from above into it.
  5. Copy the parts of the required configuration into your web.config or app.config.
    Hint: You want “targetSystems” as well as “sectionGroup” under “configSections”.
  6. Add a reference to “Tedd.AclConfig” from your main project.
  7. Add “TargetConfigLoader.InitConfig();” as first executed line in your startup app.
    Console/WinForms/WPF: As first line in “Main” function in Program.cs.
    Web project: As first line in “Application_Start()” in Global.asax. If your project doesn’t have a global.asax-file you need to add it first.

Leave a Reply