40

有谁知道是否有方法来“转换”值的特定部分,而不是替换整个值或属性?使用Web.Config转换的高级任务

例如,我有几个appSettings条目指定不同web服务的Url。这些条目在开发环境中与生产环境略有不同。有些人比其他

<!-- 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> 

注意的拳头进入,唯一的区别是“.dev”,从“.prod”没有价值的。在第二项,子域名是不同的:“MA1-lab.lab1”“ws.ServiceName2”

到目前为止,我知道我可以做这样的事情在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" /> 

然而,每次的版本为web服务的更新,我将不得不更新Web.Release.Config为好,这违背了simplfying我的web.config更新的目的。

我知道我也可以将这个URL分成不同的部分并独立更新它们,但我宁愿将它全部放在一个关键字中。

我已经浏览了可用的web.config转换但nothings似乎是齿轮towars我想完成。

这些都是我使用作为参考网站:

Vishal Joshi's blogMSDN HelpChannel9 video

任何帮助,将不胜感激!

-D

回答

66

由于事实上,你可以做到这一点,但它并不像你想象的那么简单。您可以创建自己的配置转换。我刚刚在http://sedodream.com/2010/09/09/ExtendingXMLWebconfigConfigTransformation.aspx上写了一篇非常详细的博文。但这里是hightlights:

  • 创建类库项目
  • 参考Web.Publishing.Tasks.dll (在%程序文件(x86)%的MSBuild \微软\ VisualStudio的\ V10.0 \ Web文件夹)
  • 扩展Microsoft.Web.Publishing.Tasks.Transform类
  • 实现的应用()方法
  • 将装配在一个众所周知的位置
  • 使用XDT:导入,使新的反式可
  • 使用形式变换

这里是我创建做这类取代

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); 
       } 
      } 
     } 
    } 
} 

这是网络。配置

<?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> 

下面是我的配置转换文件

<?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> 

这里是如果你正在使用Visual Studio 2013

<?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> 
+0

说过了,这太棒了!非常感谢花时间来回答这个问题,我开始放弃希望:) – 2010-09-09 13:42:41

+0

神圣的毛骨悚然,这真是太棒了!非常感谢,队友..这正是我需要:) – 2010-10-29 09:13:12

+0

这是如此可怕,没有一个更简单的方法来做到这一点。 :(感谢这个,虽然,这是非常有帮助的 – 2013-07-16 21:16:10

3

只是作为一个更新,改造后的结果,应该引用%Program Files(x86)%MSBuild \ Microsoft \ VisualStudio \ v12.0 \ Web \ Microsoft.Web.XmlTransform.dll。