Galin Iliev's blog

Software Architecture & Development

.NET External Configuration & Build Process

It is very good practice to have several environments when creating a software solution - typical environments are Development -> Integration -> Staging -> Production environments. Also having Automated Continuous Integration server like CruiseControl.NET can greatly improve teamwork and quality of developed solution. Of course having a solution build (by CruiseControl.NET) you might want to have the installation project also build... and you will need a deployment procedure so the steps would look like these:

  1. Check-in source code changes
  2. Trigger a build on CI build server for the solution
  3. Trigger a build on CI build server for the build package
  4. Execute publish script which will deploy binaries to certain environment/servers and will change app settings, connection strings etc.

Example project setup can be seen on Omar Al Zabir's blog post ASP.NET website Continuous Integration+Deployment using CruiseControl.NET, Subversion, MSBuild and Robocopy.


Of course having all changes for different environments in publish script would make it big and difficult to maintain. This is why it is better to keep all environment/servers specific settings outside of the project. One option is machine.config. And storing it in source control, of course.


Another option is having all those settings in separate folder. I wasn’t aware of this option of .NET Configuration API and I was disappointed  when I found that XInclude is not supported. Fortunately there configSource section attribute which allows to achieve same functionality. For some ( more here ) this might be well known but I found this recently and AFAIK it is not widely used.


So you can specify web.config/app.config file like this:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <connectionStrings configSource="ConnectionStrings.config" ></connectionStrings>
   4:   <appSettings configSource="settings.config"></appSettings>
   5: </configuration>

and then specify actual configuration in external files. Here are my examples for ConnectionStrings.config

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <connectionStrings>
   3:   <add name="cs1" connectionString="Data Source=myServerAddress;Failover Partner=myMirrorServer;Initial Catalog=myDataBase;Integrated Security=True;"/>
   4: </connectionStrings>

and Settings.config

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <appSettings>
   3:   <add key="s1" value="Some very important setting"/>
   4: </appSettings>


As you can see from example the only important thing is to have root element of external file named same as referenced section in the core config file.

and after that you can simply get the values as usual:

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         Console.WriteLine("cs1: {0}", ConfigurationManager.ConnectionStrings["cs1"].ConnectionString);
   6:         Console.WriteLine("s1: {0}", ConfigurationManager.AppSettings["s1"]);
   7:         Console.ReadLine();
   8:     }
   9: }


This means you can refactor configuration of existing .NET applications without having to touch the code or even recompile. Just be careful :)

Happy XML/Config refactoring :) !

Comments (1) -

  • Bubber

    7/16/2011 9:23:35 PM | Reply

    What a joy to find such clear thinking. Thanks for positng!