Chained web.config transformation

ASP.NET apps have a global configuration file called Web.config and because apps are published in several configurations (e.g. Debug and Release), there is a simple way to transform the web.config using transformation files instead of keeping two nearly identical web.config files at once. It is a great feature (it also works for App.config).

It works like this: you have a base Web.config and transformation files named Web.$(configuration).config (e.g. Web.Release.config) that transform the original Web.config (e.g. specifying smtp server) during deploy or publish.

The transformation files make it very easy to change Web.config, e.g. following snippet adds a key to the appSettings section.

<?xml version="1.0" encoding="utf-8"?>
<!-- For more information on using web.config transformation 
visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="Version" value="3.15" xdt:Transform="Insert"/>
  </appSettings>
</configuration>

You can look up info about possible transformations in the official documentation or for quick review go to the Scott Hanselman blog.

This allows one transformation, but you can have two chained transformations if you use publish profiles.

It is simple to do, in the context menu of the profile click on the Add Config Transform and Visual Studio will create a new transformation file that is applied after the build configuration transformation.

add-config-transform

In the following image you can see the result of staged transformation (Web.Debug.config and then Web.Integration.config, see red rectangle). You can see the diff between the original Web.config and transformed one using the “Preview Transform” item of the Web.$(configuration).config context menu.

 

web.config-chained-transformation

I thought it would be great, we have 5 different environments (local, CI, INT, ACC, PROD) and for each one two web.configs (i.e. 10 configs in total) that have to be kept in sync. It is a lot of rather error prone work. While testing it out, I encountered following problems:

Web.config is transformed only on publish, not build

We use Visual Studio to program and debug our application, so we simply choose Debug -> Start without debugging. That is troublesome, because the app will use the original, untransformed Web.config, because transformation is done only on Publish or Deploy and the resulting Web.config is stored somewhere else.

I often debug app, change Web.config and the IIS automatically detects that Web.config has changed and reloads the site. When I configured logging, I changed web.config a lot of time.

I am of course not the first person to encounter this, so there are some solutions. The *.csproj project file is only a MSBuild script, it can be modified.

  • Rename the base Web.config to Web.generic.config
  • Open your *.csproj file in text editor
  • Uncomment  <Target Name="AfterBuild"> target in the *.csproj. It is commented out along with   <Target Name="BeforeBuild"> target.
  • Add the TransformXml for Web.Config into the target
    <Target Name="AfterBuild">
      <TransformXml Source="Web.Generic.Config"
                    Transform="$(ProjectConfigTransformFileName)"
                    Destination="Web.Config" />  
    </Target>
    

Now, every time the project is build, the Web.config will be changed. Note that this doesn’t support chained transformation, so only build configuration is applied.

For details see the Making Visual Studio 2010 Web.config Transformations Apply on Every Build. You can also look at this forum thread that provides some other suggestions.

Sensitive information must not be in transformation file

Some information, e.g. password to our production database is not available to developers, so it can’t be in the transformation files, yet I want simple and reliable deploy to production I (as a developer) can do without our PM present. I am hoping to use a Web Deploy Parameters to do that.

References