Есть ли способ сделать «Заменить или вставить», используя преобразование web.config?

183

Я использую преобразование 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, поскольку я не всегда могу полагаться на исходный файл конфигурации, имеющий / не имеющий определенный ключ.

Есть какой-либо способ сделать это?

Крис Хейнс
источник
предоставленная вами ссылка не работает на данный момент. У вас есть другая ссылка, чтобы легко понять концепцию?
Ашиш-BeJovial
@AshishJain ссылка отлично работает для меня
Крис Хейнс

Ответы:

105

Я нашел дешевый обходной путь. Это не красиво и не будет работать очень хорошо, если у вас есть много элементов, которые должны быть «Заменить или вставить».

Сделайте «Удалить», а затем «InsertAfter | InsertBefore».

Например,

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertAfter(/configuration/system.web/authentication)">
  <deny users="?"/>
  <allow users="*"/>
</authorization>
Фу
источник
17
Если использовать VS2012, теперь есть лучшее решение. См. Ниже stackoverflow.com/a/16679201/32055
Крис Хейнс
1
будет "InsertIfMissing" вставлять и заменять при необходимости?
Джесси
Я предпочитаю этот вариант, чем другой, благодаря использованию InsertAfter. InsertIfMissing не имеет смысла, если вы все равно делаете удаление.
Шейн Кортрилл
125

В сочетании с xdt:Transform="Remove"использованием xdt:Transform="InsertIfMissing"в VS2012.

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertIfMissing">
  <deny users="?"/>
  <allow users="*"/>
</authorization>
ADW334034
источник
Отлично! Это то, чего мы так долго ждали.
Крис Хейнс
9
Это совсем не так, как запросы OP.
БрэдЛейни
2
Ответ был отредактирован, чтобы более четко продемонстрировать, как он отвечает на исходный вопрос.
Бон,
25
Я не понимаю Если вы удалите его, конечно, он будет отсутствовать, это просто вставка в этот момент, верно?
Чед Шуггинс
6
@ChadSchouggins не обязательно: Removeзадача удаляет только первое вхождение. Некоторые элементы могут иметь несколько вхождений. Я не могу представить, что вы захотите этого, но тогда это удалит первое вхождение и пропустит InsertIfMissingзадачу. Но ты был бы прав, если бы использовал RemoveAllвместо этого.
Стивен Лиекенс
89

Используйте 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 или более поздней версии).

Стивен Лиекенс
источник
7

Лучшим способом для меня было вставить элемент, только если он не существует, так как я устанавливаю только определенные атрибуты. Удаление элемента отбросило бы любые другие атрибуты основного элемента, если бы они существовали.

пример: 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, а метод удаления / вставки - нет.

Дэн
источник
1
Мне нравится эта идея, но я получаю сообщение об ошибке, если элемент уже существует "Ни один элемент в исходном документе не соответствует ...". То есть, если оно существует, «not» терпит неудачу, поэтому это ошибка.
Goodeye
Это метод, который вам нужен, когда вы используете версии XDT, которые не поддерживают новый (ish) элемент «InsertIfMissing».
Янвру