有没有办法进行“替换”或“插入”?使用Web.config转换?

我正在使用下面文章中描述的web.config转换,以便为不同的环境生成配置。

http://vishaljoshi.blogspot.com/2009/03/web-deployment-webconfig-transformation_23.html.

我可以通过匹配键来进行“替换”转换,例如

<add key="Environment" value="Live" xdt:Transform="Replace" xdt:Locator="Match(key)" />

我可以做“插入”。

<add key="UseLivePaymentService" value="true" xdt:Transform="Insert" />

但是我的确发现有用的是ReplaceOrInsert转换,因为我不能总是依赖于具有/不具有某个键的原始配置文件。

有没有办法做到这一点?

107368 次浏览

I found a cheap workaround. It ain't pretty and won't work very well if you have a lot of elements that needs to be "Replace Or Insert".

Do a "Remove" and then an "InsertAfter|InsertBefore".

For example,

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertAfter(/configuration/system.web/authentication)">
<deny users="?"/>
<allow users="*"/>
</authorization>

A better method for me was to insert the element only if it doesn't exist since I am only setting certain attributes. Removing the element would discard any other attributes of the main element if they existed.

example: web.config (without element)

<serviceBehaviors>
<behavior name="Wcf.ServiceImplementation.AllDigitalService_Behavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>

web.config (with element)

<serviceBehaviors>
<behavior name="Wcf.ServiceImplementation.AllDigitalService_Behavior">
<serviceDebug httpsHelpPageEnabled="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>

Using the Locator with an XPath expression, I add the node if it doesn't exist and then set my attribute:

<serviceDebug xdt:Transform="Insert"
xdt:Locator="XPath(/configuration/system.serviceModel/behaviors/serviceBehaviors/behavior[not(serviceDebug)])" />
<serviceDebug includeExceptionDetailInFaults="true" xdt:Transform="SetAttributes" />

both resulting web.config files have includeExceptionDetailInFaults="true" and the second one preserves the httpsHelpPageEnabled attribute where the remove/insert method would not.

In conjunction with xdt:Transform="Remove" use xdt:Transform="InsertIfMissing" in VS2012.

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertIfMissing">
<deny users="?"/>
<allow users="*"/>
</authorization>

Use the InsertIfMissing transformation to ensure that the appSetting exists.
Then use the Replace transformation to set its value.

<appSettings>
<add key="Environment" xdt:Transform="InsertIfMissing" xdt:Locator="Match(key)" />
<add key="Environment" value="Live" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>

You could also use the SetAttributes transformation instead of Replace. The difference is that SetAttributes does not touch child nodes.

<appSettings>
<add key="UseLivePaymentService" xdt:Transform="InsertIfMissing" xdt:Locator="Match(key)" />
<add key="UseLivePaymentService" value="true" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>

These techniques are much better than remove+insert because existing nodes are not moved to the bottom of their parent node. New nodes are appended at the end. Existing nodes stay where they are in the source file.

This answer applies only to newer versions of Visual Studio (2012 or newer).