有没有办法使用web.config转换执行“替换或插入”操作?

199

我正在使用下面帖子中描述的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转换,因为我不能总是依赖于原始配置文件是否具有某个键。

有没有什么办法可以做到这一点?


您提供的链接目前无法使用。您是否有其他链接可以更轻松地理解这个概念? - Ashish-BeJovial
1
@AshishJain,链接对我来说很好用。 - Chris Haines
4个回答

143

在VS2012中,与xdt:Transform="Remove"结合使用xdt:Transform="InsertIfMissing"

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

太完美了!这就是我们一直在等待的。 - Chris Haines
是否有类似的“InsertAfterIfMissing”函数? - Piers Karsenbarg
10
这完全没有满足OP的要求。 - BradLaney
3
答案已经进行编辑以更清晰地展示它如何回答原始问题。 - Bon
26
我不理解。如果你移除它,当然它就会失踪了,此时它只是一个插入点,对吧? - Chad Schouggins
7
@ChadSchouggins并非一定如此:Remove任务仅删除第一次出现的元素。有些元素可能会多次出现。我想象不出您希望这样做,但那么它将删除第一次出现并跳过InsertIfMissing任务。但如果他使用RemoveAll,那么您就是正确的。 - Steven Liekens

108

我找到了一个便宜的解决方法。虽然不太美观,但如果您需要“替换或插入”很多元素,则可能无法很好地工作。

先执行“删除”,然后再执行“InsertAfter|InsertBefore”。

例如:

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

18
如果使用VS2012,现在有更好的解决方案。请见下文:https://dev59.com/xW025IYBdhLWcg3w6KOO#16679201 - Chris Haines
1
如果需要,"InsertIfMissing"会插入并替换吗? - Jessy
我更喜欢使用InsertAfter而不是其他选项,因为它能更好地满足我的需求。如果你打算执行删除操作,那么InsertIfMissing就没有任何意义。 - Shane Courtrille

102
使用InsertIfMissing变换确保appSetting存在。
然后使用Replace变换设置其值。
<appSettings>
  <add key="Environment" xdt:Transform="InsertIfMissing" xdt:Locator="Match(key)" />
  <add key="Environment" value="Live" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>

您也可以使用SetAttributes转换而不是Replace。不同之处在于,SetAttributes不会影响子节点。

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

这些技术比删除+插入要好得多,因为现有节点不会移动到其父节点的底部。新节点将附加在结尾。现有节点保持在源文件中的原位。

此答案仅适用于较新版本的Visual Studio(2012或更高版本)。


8

对我来说更好的方法是仅在元素不存在时插入该元素,因为我只设置特定属性。如果删除元素,则会丢弃主元素的任何其他属性(如果存在)。

示例: web.config(不包含元素)

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

web.config(带元素)

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

使用XPath表达式与定位器,如果节点不存在,则添加节点,并设置属性:
<serviceDebug xdt:Transform="Insert"
  xdt:Locator="XPath(/configuration/system.serviceModel/behaviors/serviceBehaviors/behavior[not(serviceDebug)])" />
<serviceDebug includeExceptionDetailInFaults="true" xdt:Transform="SetAttributes" />

两个生成的web.config文件都有includeExceptionDetailInFaults="true"属性,而第二个保留了httpsHelpPageEnabled属性,而remove/insert方法则不会。


1
我喜欢这个想法,但如果元素已经存在,我会收到一个错误消息“源文档中没有任何元素匹配...”。也就是说,如果它已经存在,“not”操作失败了,因此会出现错误。 - goodeye
这是你在使用不支持新的“InsertIfMissing”元素的XDT版本时所需的技巧。 - IanBru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接