【问题标题】:Is there any way to do a "Replace Or Insert" using web.config transformation?有没有办法使用 web.config 转换进行“替换或插入”?
【发布时间】:2011-08-09 14:44:41
【问题描述】:

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

有什么办法吗?

【问题讨论】:

  • 您提供的链接目前无效。您是否有任何其他链接可以轻松理解该概念?
  • @AshishJain 该链接对我来说很好

标签: asp.net web-config-transform xslt xdt-transform


【解决方案1】:

我找到了一个便宜的解决方法。如果您有很多需要“替换或插入”的元素,它并不漂亮,并且不会很好地工作。

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

例如,

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

【讨论】:

  • 如果使用VS2012,现在有更好的解决方案。见下文stackoverflow.com/a/16679201/32055
  • 是否需要“InsertIfMissing”插入和替换?
  • 由于使用了 InsertAfter,我更喜欢这个选项。如果您仍然在执行 Remove,则 InsertIfMissing 毫无意义。
【解决方案2】:

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

示例: 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 表达式的 Locator,如果节点不存在,我会添加它,然后设置我的属性:

<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 方法则不会。

【讨论】:

  • 我喜欢这个想法,但如果元素已经存在“源文档中没有元素匹配...”,我会收到错误消息。也就是说,如果它存在,“不”就失败了,所以这是一个错误。
  • 这是您在使用不支持新的(ish)“InsertIfMissing”元素的 XDT 版本时需要的技术。
【解决方案3】:

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

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

【讨论】:

  • 完美!这就是我们一直在等待的。
  • 这根本不符合 OP 的要求。
  • 对答案进行了编辑,以更清楚地展示它是如何回答原始问题的。
  • 我不明白。如果你删除它,它当然会丢失,它只是一个插入,对吧?
  • @ChadSchouggins 不一定:Remove 任务仅删除第一次出现。某些元素可以多次出现。我无法想象你会想要这个,但它会删除第一次出现并跳过InsertIfMissing 任务。但如果他改用RemoveAll,你就对了。
【解决方案4】:

使用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 或更新版本)。

【讨论】:

    猜你喜欢
    • 2014-07-05
    • 2013-08-11
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 2022-06-12
    • 2018-09-23
    • 2018-02-23
    相关资源
    最近更新 更多