One of the nice features of Visual Studio 2012(and also Visual Studio 2010) is the ability to use Web.config transformations.
However the list of supported transforms is somewhat limited. I was looking for a way to execute a transformation only if a specific element doesn’t exist yet in your root web.config file. I discovered that Web.config transform engine can be extended to support additional transformations.
On the AppHarbor blog, I found a sample transformation that exactly did what I needed:
If you want to use this transform you need to add it using the xdt:Import element. You can place that element inside the xml document anywhere immediately under the root element. This element will allow us to utilize our own transform class. It only has 3 possible attributes.
So the import will look like this in your transformation XML:
From that moment one you can start applying it:
The only disadvantage I think is that you have to install this transform assembly on all developer pc’s if they want to execute these transformations locally.
However the list of supported transforms is somewhat limited. I was looking for a way to execute a transformation only if a specific element doesn’t exist yet in your root web.config file. I discovered that Web.config transform engine can be extended to support additional transformations.
On the AppHarbor blog, I found a sample transformation that exactly did what I needed:
using System.Linq; using System.Xml; using Microsoft.Web.Publishing.Tasks; namespace AppHarbor.TransformTester.Transforms { public class Merge : Transform { public Merge() : base(TransformFlags.UseParentAsTargetNode) {} protected override void Apply() { Apply((XmlElement)TargetNode, (XmlElement)TransformNode); } public void Apply(XmlElement targetElement, XmlElement transformElement) { var targetChildElement = targetElement.ChildNodes.OfType<XmlElement>() .FirstOrDefault(x => x.LocalName == transformElement.LocalName); if (targetChildElement == null) { targetElement.AppendChild(transformElement); return; } foreach (var transformChildElement in transformElement.ChildNodes .OfType<XmlElement>()) { Apply(targetChildElement, transformChildElement); } } } }
- namespace – This is the namespace which the transform is contained in
- path – This is the full path to the assembly
- assembly – This is the assembly name which contains the transform
So the import will look like this in your transformation XML:
<xdt:Import assembly="AppHarbor.TransformTester" namespace="AppHarbor.TransformTester.Transforms"/>
From that moment one you can start applying it:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <connectionStrings xdt:Transform="Merge" /> <connectionStrings> <add name="bar" connectionString="value" xdt:Transform="Insert"/> </connectionStrings> </configuration>
The only disadvantage I think is that you have to install this transform assembly on all developer pc’s if they want to execute these transformations locally.