【问题标题】:Advanced tasks using Web.Config transformation使用 Web.Config 转换的高级任务
【发布时间】:2011-02-24 07:29:46
【问题描述】:

有谁知道是否有办法“转换”值的特定部分而不是替换整个值或属性?

例如,我有几个 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,这违背了简化 web.config 更新的目的。

我知道我也可以将该 URL 拆分为不同的部分并独立更新它们,但我宁愿将所有内容集中在一个键中。

我查看了可用的 web.config 转换,但似乎没有什么适合我想要完成的。

这些是我用作参考的网站:

Vishal Joshi's blogMSDN HelpChannel9 video

任何帮助将不胜感激!

-D

【问题讨论】:

    标签: asp.net visual-studio-2010 web-config transformation web-deployment


    【解决方案1】:

    作为更新,如果您使用的是 Visual Studio 2013,则应改为引用 %Program Files (x86)%MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.XmlTransform.dll。

    【讨论】:

      【解决方案2】:

      事实上,您可以做到这一点,但并不像您想象的那么容易。您可以创建自己的配置转换。我刚刚在http://sedodream.com/2010/09/09/ExtendingXMLWebconfigConfigTransformation.aspx 上写了一篇非常详细的博客文章。但这里有重点:

      • 创建类库项目
      • 参考 Web.Publishing.Tasks.dll (在 %Program Files (x86)%MSBuild\Microsoft\VisualStudio\v10.0\Web 文件夹下)
      • 扩展 Microsoft.Web.Publishing.Tasks.Transform 类
      • 实现 Apply() 方法
      • 将组件放置在众所周知的位置
      • 使用 xdt:Import 使新转换可用
      • 使用变换

      这是我创建的用于替换的类

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

      这是 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>
      

      这是我的配置转换文件

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

      这是改造后的结果

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

      【讨论】:

      • 说,这太棒了!非常感谢您花时间回答这个问题,我开始失去希望了:)
      • 天哪,这太棒了!非常感谢,伙计..这正是我需要的:)
      • 太糟糕了,没有更简单的方法可以做到这一点。 :( 谢谢你,这非常有帮助。
      • 这对我帮助很大。但是,有一件事是您的类不会将转换应用于所有匹配的节点。我已经修改了 Apply 方法来做到这一点:protected override void Apply() { foreach (XmlNode target in this.TargetNodes) { foreach (XmlAttribute att in target.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); } } } }
      猜你喜欢
      • 1970-01-01
      • 2011-12-02
      • 2015-03-06
      • 1970-01-01
      • 2014-06-24
      • 1970-01-01
      • 2015-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多