Using 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.
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:
<?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:
<?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 :
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.
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.)
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).
The XDT source can be found here: 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
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With