Byon January 6, 2011 12:00 PM
I have built a fairly involved set of MSBuild scripts to build and deploy our web applications to our servers. At the time I was building all of this, I found that the Web Deployment Projects that were available for Visual Studio 2005 and 2008 were not sufficient to meet our needs, in part because we use Hudson for CI instead of Team Foundation Server, but that’s another issue entirely. To support making changes to our Web.configs during builds to either our Test environment or our Production environment, I’d written a few MSBuild tasks to do simple XML Translation.
However, as work on my build scripts is ancillary to my primary job function, my solution was not as polished as I would have liked. It required an XML file for each replacement, which meant that each build configuration had several files that needed to be applied. It required a fair amount of familiarity with XPath. It works, and it works well, but it just isn’t as user-friendly as I’d like.
So when I saw the new Web.config Transformation Syntax, I was really pleased. A single file per configuration, and I don’t need to use XPath, though I can if I want? Sign me up!
However, by default, those files only appear to be applied when you use the “Build Deployment Package” option in the context menu of a Web Application project. This really didn’t fit into our current build system, and it made a lot more sense to adapt the Transformation Task to my build scripts than modify my build system.
In your common build file, you’ll want to add the following PropertyGroup:
<PropertyGroup> <OutputWebConfig>$(TempBuildDir)\web.config</OutputWebConfig> <OriginalWebConfig>$(ProjectDir)\web.config</OriginalWebConfig> <TransformWebConfig>$(ProjectDir)\web.$(Configuration).config</TransformWebConfig> </PropertyGroup>
The TempBuildDir property is a temporary folder where I copy deployment files so I don’t modify anything in the project directory before pushing it out to the server. ProjectDir is the path to the Web Application Project and is defined in the project-specific MSBuild file. However, these three properties are needed for the task to succeed. With the properties defined, you can then add the task:
<UsingTask AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" TaskName="TransformXml" /> <Target Name="Core_TransformWebConfig" Condition="Exists('$(TransformWebConfig)')"> <TransformXml Destination="$(OutputWebConfig)" Source="$(OriginalWebConfig)" Transform="$(TransformWebConfig)" /> </Target>
This target will need to be added to the dependencies of one of your other tasks, prior to the code being pushed to the server.
We are in the process of moving our web.config transformations to this system, as it’s a cleaner syntax. It is fairly easy to integrate into your build system without needing to make a drastic change to your build system, and with the Exists conditional, I’m actually using both systems in tandem, while I wait to convert some of my older projects.