Existe alguma maneira de fazer uma "Substituir ou Inserir" usando a transformação web.config?

183

Estou usando a transformação web.config, conforme descrito na publicação abaixo, para gerar configurações para diferentes ambientes.

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

Eu posso fazer uma transformação "Substituir" combinando com a chave, por exemplo

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

E eu posso fazer "inserções", por exemplo

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

Mas o que eu realmente consideraria útil é uma transformação ReplaceOrInsert, pois nem sempre posso confiar no arquivo de configuração original que possui / não possui uma determinada chave.

Há alguma maneira de fazer isso?

Chris Haines
fonte
o link que você forneceu não está funcionando no momento. Você tem algum outro link para entender o conceito facilmente?
Ashish-BeJovial
@AshishJain o link fina funciona para mim
Chris Haines

Respostas:

105

Encontrei uma solução alternativa barata. Não é bonito e não funcionará muito bem se você tiver muitos elementos que precisam ser "Substituir ou inserir".

Faça um "Remover" e um "InsertAfter | InsertBefore".

Por exemplo,

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertAfter(/configuration/system.web/authentication)">
  <deny users="?"/>
  <allow users="*"/>
</authorization>
um phu
fonte
17
Se você estiver usando o VS2012, agora há uma solução melhor. Veja abaixo stackoverflow.com/a/16679201/32055
Chris Haines
1
irá "InsertIfMissing" inserir e substituir, se necessário?
Jessy
Eu prefiro essa opção do que a outra, graças ao uso do InsertAfter. InsertIfMissing não faz sentido se você estiver fazendo um Remove de qualquer maneira.
Shane Courtrille
125

Em conjunto com o xdt:Transform="Remove"uso xdt:Transform="InsertIfMissing"no VS2012.

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertIfMissing">
  <deny users="?"/>
  <allow users="*"/>
</authorization>
ADW334034
fonte
Perfeito! É isso que estamos esperando.
Chris Haines
9
Isso não funciona como solicitações de OP.
BradLaney
2
A resposta foi editada para demonstrar mais claramente como responde à pergunta original.
Bon
25
Eu não entendo. Se você removê-lo, é claro que vai faltar, é apenas uma inserção nesse ponto, certo?
Chad Schouggins 31/07
6
@ChadSchouggins não necessariamente: a Removetarefa remove apenas a primeira ocorrência. Alguns elementos podem ter várias ocorrências. Não consigo imaginar que você queira isso, mas isso removeria a primeira ocorrência e pularia a InsertIfMissingtarefa. Mas você teria razão se ele usasse RemoveAll.
22615 Steven Stevkens #
89

Use a InsertIfMissingtransformação para garantir que o appSetting exista.
Em seguida, use a Replacetransformação para definir seu valor.

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

Você também pode usar a SetAttributestransformação em vez de Replace. A diferença é que SetAttributesnão toca nos nós filhos.

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

Essas técnicas são muito melhores que remover + inserir porque os nós existentes não são movidos para a parte inferior do nó pai. Novos nós são anexados no final. Os nós existentes permanecem onde estão no arquivo de origem.

Esta resposta se aplica apenas a versões mais recentes do Visual Studio (2012 ou mais recente).

Steven Liekens
fonte
7

Um método melhor para mim era inserir o elemento apenas se ele não existir, pois estou definindo apenas alguns atributos. A remoção do elemento descartaria quaisquer outros atributos do elemento principal se eles existissem.

exemplo: web.config (sem elemento)

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

web.config (com elemento)

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

Usando o Locator com uma expressão XPath, adiciono o nó se ele não existir e defino meu atributo:

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

os dois arquivos web.config resultantes têm includeExceptionDetailInFaults = "true" e o segundo preserva o atributo httpsHelpPageEnabled, onde o método remover / inserir não.

Dan
fonte
1
Eu gosto dessa ideia, mas estou recebendo um erro se o elemento já existir "Nenhum elemento no documento de origem corresponde ...". Ou seja, se existir, o "não" está falhando, por isso é um erro.
21412 goodeye
Essa é a técnica necessária quando você usa versões do XDT que não oferecem suporte ao novo elemento (ish) "InsertIfMissing".
IanBru