Using Visual Studio 2013 Premium.
使用Visual Studio 2013 Premium。
Goal: I have multiple WCF services defined in a web.config. To keep the web.config file readable and make adding services simpler, I want to use VS2013's XML transforms to add some boilerplate elements to each service definition for my dev/production environments.
目标:我在web.config中定义了多个WCF服务。为了使web.config文件可读并使添加服务更简单,我想使用VS2013的XML转换为我的开发/生产环境的每个服务定义添加一些样板元素。
Problem: I have multiple <service>
tags, but only the first one is transformed properly.
问题:我有多个
Here's a simplified version of my Web.Config with two services defined:
这是我的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>
I want to create a Metadata exchange endpoint and do some other things (not shown) to each <service>
tag.
我想创建一个元数据交换端点,并为每个
Here's a simplified Web.Debug.Config showing only the MetadataExchange endpoint:
这是一个简化的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>
I get this:
我明白了:
<?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>
I've tried these variations on the XPath
argument in the xdt:Locator
attribute of the :
我已尝试在xdt:Locator属性中的XPath参数的这些变体:
1. /configuration/system.serviceModel/services/service
2. /configuration/system.serviceModel/services//service
3. //service
All of which transform only the 1st <service>
section.
所有这些只转换第一个
I've tried putting the xdt:Locator
attribute on the <endpoint>
tag, etc. to no avail.
我试过在
I have multiple XPath visualizers and tools, and all of them match both <service>
tags when used with XPath #1 above. Also, this error happens in "Preview Transform" and the web deployment tool preview.
我有多个XPath可视化工具和工具,当与上面的XPath#1一起使用时,它们都匹配
What am I doing wrong?
我究竟做错了什么?
(My workaround, at this point, is to include the Mex endpoint and the rest of the debugging cruft in my original Web.Config, and then remove it with "RemoveAll()", but that makes my Web.Config really cluttered and hard to read.)
(我的解决方法是,在这一点上,将Mex端点和其余调试内容包含在我原来的Web.Config中,然后使用“RemoveAll()”将其删除,但这会使我的Web.Config真的变得混乱和困难读书。)
1 个解决方案
#1
1
I recently ran into this issue, and it turns out it isn't supported.
我最近遇到了这个问题,事实证明它不受支持。
My work around was adding a custom transform, and using that instead of Insert. The issue with their implementation is that the default Insert only modifies the first value (even though the XPath expression does retrieve a list).
我的工作是添加自定义转换,并使用它而不是插入。它们的实现问题是默认的Insert只修改第一个值(即使XPath表达式确实检索了一个列表)。
The XDT source can be found here: http://xdt.codeplex.com/
可在此处找到XDT源:http://xdt.codeplex.com/
The article I ran across that got me in the right direction: http://blog.appharbor.com/2012/07/27/custom-web-config-transforms-and-merges
我遇到的文章让我朝着正确的方向前进:http://blog.appharbor.com/2012/07/27/custom-web-config-transforms-and-merges
What I did is add a new class to their source, and was able to achieve exactly what you are looking for.
我所做的是在他们的源代码中添加一个新类,并且能够实现您正在寻找的内容。
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);
}
}
#1
1
I recently ran into this issue, and it turns out it isn't supported.
我最近遇到了这个问题,事实证明它不受支持。
My work around was adding a custom transform, and using that instead of Insert. The issue with their implementation is that the default Insert only modifies the first value (even though the XPath expression does retrieve a list).
我的工作是添加自定义转换,并使用它而不是插入。它们的实现问题是默认的Insert只修改第一个值(即使XPath表达式确实检索了一个列表)。
The XDT source can be found here: http://xdt.codeplex.com/
可在此处找到XDT源:http://xdt.codeplex.com/
The article I ran across that got me in the right direction: http://blog.appharbor.com/2012/07/27/custom-web-config-transforms-and-merges
我遇到的文章让我朝着正确的方向前进:http://blog.appharbor.com/2012/07/27/custom-web-config-transforms-and-merges
What I did is add a new class to their source, and was able to achieve exactly what you are looking for.
我所做的是在他们的源代码中添加一个新类,并且能够实现您正在寻找的内容。
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);
}
}