Transformation of Configuration Files in Build Process

January 8th 2012 ASP.NET Visual Studio SlowCheetah

Web.config transformations are a great but often overlooked feature introduced with ASP.NET 4.0. They provide a simple way to define a different configuration for Debug and Release builds of your project by only specifying the differences (typically only connection strings and similar settings) in a separate transformation file while keeping the core of the configuration file common and consequentially making it easier to manage.

Unfortunately files aren't transformed until the web deployment package is created, i.e. they aren't part of the core build process. This makes the transformations more difficult to use in some scenarios such as having a different configuration file for automated testing as a part of the build process.

Since the transformation is done by the TransformXml MSBuild task in Microsoft.Web.Publishing.Tasks.dll assembly there is a way to make this work by modifying the project file manually, though. Here is a snippet that I added to my project file (line break in the AssemblyFile added for readability only):

<UsingTask TaskName="TransformXml"
                         v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
    <MakeDir Directories="obj\$(Configuration)"
             Condition="!Exists('obj\$(Configuration)')" />
    <TransformXml Source="Web.Config"
                  Condition="Exists('Web.$(Configuration).config')" />

As you can see the transformed configuration file is put inside the obj folder from where I copy it to the desired final location before running the tests. I find this a suitable spot for it unless you are precompiling views in your ASP.NET MVC project. A web.config file anywhere in obj folder brakes the build so you'll have to put the file elsewhere or make sure you delete it before precompiling the views.

If you want to make this work on your build server without having Visual Studio installed on it, there is one more step remaining. The above mentioned assembly is not installed with .NET SDK meaning that you have to copy it there from your development machine. The file is located in the MSBuild extension folder, i.e. C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\ by default.

Transformation files displayed under the original file

This takes care of transforming web.config files during build. How about transforming app.config files and even other XML files in your projects? I guess it would be possible to use the same MSBuild task on them but no Visual Studio support for transforming those files would mean even more tempering with project files to make transformation files appear under the file they are used to transform.

This is where SlowCheetah – XML Transforms Visual Studio extension can help. After installing it you can define transformations for app.config the same way you are already doing it with web.config files. The transformation is part of the build process in this case, i.e. the transformed file is put in its usual spot in the build output folder (usually bin) instead of the original one. It couldn't get any simpler.

As an added bonus the extension features support for previewing the results of the transformation: after right clicking the transformation file and selecting the Preview Transform command a diff window will open graphically showing the differences between the original and the transformed file. Of course this works with web.config transformations as well making the debugging of transformations much simpler. A good reason in itself to install this extension.

To avoid failed builds on your build server as well as with the other members of your team not having this extension installed it's best that you copy the SlowCheetah MSBuild targets and the corresponding assembly containing the tasks to your solution directory and put it in source control. In this case you'll again have to modify the project file to set the new path. Just search for the SlowCheetahTargets property definition and modify the path accordingly (line breaks added for readability):

    <SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' ">

Are there any ways to make your life simpler by using configuration transformations in your projects?

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Creative Commons License