【问题标题】:Web.Config transforms: Using Insert() to transform multiple elementsWeb.Config 转换:使用 Insert() 转换多个元素
【发布时间】:2014-03-04 20:27:19
【问题描述】:

使用 Visual Studio 2013 Premium。

目标:我在 web.config 中定义了多个 WCF 服务。为了保持 web.config 文件的可读性并使添加服务更简单,我想使用 VS2013 的 XML 转换为我的开发/生产环境的每个服务定义添加一些样板元素。

问题:我有多个<service>标签,但只有第一个被正确转换。

这是我的 Web.Config 的简化版本,其中定义了两个服务:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="AppName.AccountManagerService">
        <endpoint address="AccountManagerService" binding="netTcpBinding"
          bindingConfiguration="" contract="Shared.Contracts.IAccountManagerService" />
      </service>
      <service name="AppName.TicketManagerService">
        <endpoint address="TicketManagerService" binding="netTcpBinding"
          bindingConfiguration="" contract="Shared.Contracts.ITicketManagerService" />
      </service>
    </services>
</configuration>

我想创建一个元数据交换端点并对每个 &lt;service&gt; 标记执行一些其他操作(未显示)。

这是一个简化的 Web.Debug.Config,仅显示 MetadataExchange 端点:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.serviceModel>
    <services>
      <service xdt:Locator="XPath(/configuration/system.serviceModel/services/service)">
        <endpoint kind="mexEndpoint"
                  address="mex"
                  xdt:Transform="Insert()"
                />
      </service>
    </services>
  </system.serviceModel>
</configuration>

我明白了:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="AppName.AccountManagerService">
        <endpoint address="AccountManagerService" binding="netTcpBinding"
          bindingConfiguration="" contract="Shared.Contracts.IAccountManagerService" />

        <!-- Yay! -->
        <endpoint kind="mexEndpoint"
                  address="mex"
                />

      </service>
      <service name="AppName.TicketManagerService">
        <endpoint address="TicketManagerService" binding="netTcpBinding"
          bindingConfiguration="" contract="Shared.Contracts.ITicketManagerService" />

        <!-- Hey, where's the endpoint tag for this one? -->

      </service>
    </services>
</configuration>

我在xdt:Locator 属性中的XPath 参数上尝试了这些变体:

1. /configuration/system.serviceModel/services/service
2. /configuration/system.serviceModel/services//service
3. //service

所有这些都转换第一个&lt;service&gt; 部分。

我尝试将xdt:Locator 属性放在&lt;endpoint&gt; 标记等上,但无济于事。

我有多个 XPath 可视化工具和工具,当与上面的 XPath #1 一起使用时,它们都匹配 both &lt;service&gt; 标记。此外,此错误发生在“预览转换”和 Web 部署工具预览中。

我做错了什么?

(此时,我的解决方法是在我的原始 Web.Config 中包含 Mex 端点和其余调试内容,然后使用“RemoveAll()”将其删除,但这使得我的 Web.Config 真的杂乱无章,难以阅读。)

【问题讨论】:

标签: asp.net xml wcf web.config-transform


【解决方案1】:

我最近遇到了这个问题,结果发现它不受支持。

我的解决方法是添加一个自定义转换,并使用它而不是插入。他们实现的问题是默认的 Insert 只修改第一个值(即使 XPath 表达式确实检索了一个列表)。

XDT 源可以在这里找到:http://xdt.codeplex.com/

我看到的那篇文章让我找到了正确的方向:http://blog.appharbor.com/2012/07/27/custom-web-config-transforms-and-merges

我所做的是向他们的源代码添加一个新类,并且能够完全实现您正在寻找的内容。

internal class InsertMultiple : Transform
{
    public InsertMultiple()
    {
        //this is the line that allows it to apply the transform for all nodes 
        //that were located with your XPath expression.
        ApplyTransformToAllTargetNodes = true;
    }

    protected override void Apply()
    {
        CommonErrors.ExpectNoArguments(Log, TransformNameShort, ArgumentString);

        TargetNode.AppendChild(TransformNode);

        Log.LogMessage(MessageType.Verbose, SR.XMLTRANSFORMATION_TransformMessageInsert, TransformNode.Name);
    }
}

【讨论】:

    猜你喜欢
    • 2011-07-07
    • 2011-05-26
    • 2012-07-28
    • 2011-08-02
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    • 2012-09-30
    • 2019-08-12
    相关资源
    最近更新 更多