Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advanced tasks using Web.Config transformation

Does anyone know if there is a way to "transform" specific sections of values instead of replacing the whole value or an attribute?

For example, I've got several appSettings entries that specify the Urls for different webservices. These entries are slightly different in the dev environment than the production environment. Some are less trivial than others

<!-- DEV ENTRY --> <appSettings>  <add key="serviceName1_WebsService_Url" value="http://wsServiceName1.dev.domain.com/v1.2.3.4/entryPoint.asmx" />  <add key="serviceName2_WebsService_Url" value="http://ma1-lab.lab1.domain.com/v1.2.3.4/entryPoint.asmx" /> </appSettings>  <!-- PROD ENTRY --> <appSettings>  <add key="serviceName1_WebsService_Url" value="http://wsServiceName1.prod.domain.com/v1.2.3.4/entryPoint.asmx" />  <add key="serviceName2_WebsService_Url" value="http://ws.ServiceName2.domain.com/v1.2.3.4/entryPoint.asmx" /> </appSettings> 

Notice that on the fist entry, the only difference is ".dev" from ".prod". On the second entry, the subdomain is different: "ma1-lab.lab1" from "ws.ServiceName2"

So far, I know I can do something like this in the Web.Release.Config:

<add xdt:Locator="Match(key)" xdt:Transform="SetAttributes(value)" key="serviceName1_WebsService_Url" value="http://wsServiceName1.prod.domain.com/v1.2.3.4/entryPoint.asmx" /> <add xdt:Locator="Match(key)" xdt:Transform="SetAttributes(value)" key="serviceName2_WebsService_Url" value="http://ws.ServiceName2.domain.com/v1.2.3.4/entryPoint.asmx" /> 

However, everytime the Version for that webservice is updated, I would have to update the Web.Release.Config as well, which defeats the purpose of simplfying my web.config updates.

I know I could also split that URL into different sections and update them independently, but I rather have it all in one key.

I've looked through the available web.config Transforms but nothings seems to be geared towars what I am trying to accomplish.

These are the websites I am using as a reference:

Vishal Joshi's blog, MSDN Help, and Channel9 video

Any help would be much appreciated!

-D

like image 998
Diego C. Avatar asked May 26 '10 17:05

Diego C.


People also ask

What is web config transform?

A Web. config transformation file contains XML markup that specifies how to change the Web. config file when it is deployed. You can specify different changes for specific build configurations and for specific publish profiles.

What is the web config file used for?

A web. config file is a Windows file that lets you customize the way your site or a specific directory on your site behaves. For example, if you place a web. config file in your root directory, it will affect your entire site (www.coolexample.com).

What is Xdt transformation?

XDT is a simple and straight forward method of transforming the web. config during publishing/packaging. Transformation actions are specified using XML attributes defined in the XML-Document-Transform namespace, that is mapped to the xdt prefix.

How do I create a new transformation in web config?

If you have a web application project, Right-click on web. config and choose Add Config Transform. This will add any config transforms that are missing from your project based on build configurations (i.e. if you have Production and Staging build configs, both will get a transform added).


1 Answers

As a matter of fact you can do this, but it is not as easy as you might think. You can create your own config transformation. I have just written a very detailed blog post at http://sedodream.com/2010/09/09/ExtendingXMLWebconfigConfigTransformation.aspx regarding this. But here are the hightlights:

  • Create Class Library project
  • Reference Web.Publishing.Tasks.dll (under %Program Files (x86)%MSBuild\Microsoft\VisualStudio\v10.0\Web folder)
  • Extend Microsoft.Web.Publishing.Tasks.Transform class
  • Implement the Apply() method
  • Place the assembly in a well known location
  • Use xdt:Import to make the new transform available
  • Use transform

Here is the class I created to do this replace

namespace CustomTransformType {     using System;     using System.Text.RegularExpressions;     using System.Xml;     using Microsoft.Web.Publishing.Tasks;      public class AttributeRegexReplace : Transform     {         private string pattern;         private string replacement;         private string attributeName;          protected string AttributeName         {             get             {                 if (this.attributeName == null)                 {                     this.attributeName = this.GetArgumentValue("Attribute");                 }                 return this.attributeName;             }         }         protected string Pattern         {             get             {                 if (this.pattern == null)                 {                     this.pattern = this.GetArgumentValue("Pattern");                 }                  return pattern;             }         }          protected string Replacement         {             get             {                 if (this.replacement == null)                 {                     this.replacement = this.GetArgumentValue("Replacement");                 }                  return replacement;             }         }          protected string GetArgumentValue(string name)         {             // this extracts a value from the arguments provided             if (string.IsNullOrWhiteSpace(name))              { throw new ArgumentNullException("name"); }              string result = null;             if (this.Arguments != null && this.Arguments.Count > 0)             {                 foreach (string arg in this.Arguments)                 {                     if (!string.IsNullOrWhiteSpace(arg))                     {                         string trimmedArg = arg.Trim();                         if (trimmedArg.ToUpperInvariant().StartsWith(name.ToUpperInvariant()))                         {                             int start = arg.IndexOf('\'');                             int last = arg.LastIndexOf('\'');                             if (start <= 0 || last <= 0 || last <= 0)                             {                                 throw new ArgumentException("Expected two ['] characters");                             }                              string value = trimmedArg.Substring(start, last - start);                             if (value != null)                             {                                 // remove any leading or trailing '                                 value = value.Trim().TrimStart('\'').TrimStart('\'');                             }                             result = value;                         }                     }                 }             }             return result;         }          protected override void Apply()         {             foreach (XmlAttribute att in this.TargetNode.Attributes)             {                 if (string.Compare(att.Name, this.AttributeName, StringComparison.InvariantCultureIgnoreCase) == 0)                 {                     // get current value, perform the Regex                     att.Value = Regex.Replace(att.Value, this.Pattern, this.Replacement);                 }             }         }     } } 

Here is web.config

<?xml version="1.0"?> <configuration>   <appSettings>     <add key="one" value="one"/>     <add key="two" value="partial-replace-here-end"/>     <add key="three" value="three here"/>   </appSettings> </configuration> 

Here is my config transform file

<?xml version="1.0"?>  <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">    <xdt:Import path="C:\Program Files (x86)\MSBuild\Custom\CustomTransformType.dll"               namespace="CustomTransformType" />    <appSettings>     <add key="one" value="one-replaced"           xdt:Transform="Replace"           xdt:Locator="Match(key)" />     <add key="two" value="two-replaced"           xdt:Transform="AttributeRegexReplace(Attribute='value', Pattern='here',Replacement='REPLACED')"           xdt:Locator="Match(key)"/>   </appSettings> </configuration> 

Here is the result after transformation

<?xml version="1.0"?> <configuration>   <appSettings>     <add key="one" value="one-replaced"/>     <add key="two" value="partial-replace-REPLACED-end"/>     <add key="three" value="three here"/>   </appSettings> </configuration> 
like image 176
Sayed Ibrahim Hashimi Avatar answered Oct 07 '22 03:10

Sayed Ibrahim Hashimi