¿Hay alguna forma de hacer un "Reemplazar o insertar" usando la transformación web.config?

183

Estoy usando la transformación web.config como se describe en la publicación a continuación para generar configuraciones para diferentes entornos.

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

Puedo hacer una transformación "Reemplazar" haciendo coincidir la tecla, p. Ej.

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

Y puedo hacer "Inserts", por ejemplo

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

Pero lo que realmente me parece útil es una transformación ReplaceOrInsert, ya que no siempre puedo confiar en que el archivo de configuración original tenga / no tenga una determinada clave.

¿Hay alguna forma de hacer esto?

Chris Haines
fuente
el enlace que proporcionó no funciona a partir de ahora. ¿Tienes algún otro enlace para entender el concepto fácilmente?
Ashish-BeJovial
@AshishJain el enlace funciona bien para mí
Chris Haines

Respuestas:

105

Encontré una solución barata. No es bonito y no funcionará muy bien si tiene muchos elementos que deben ser "Reemplazar o insertar".

Haga un "Eliminar" y luego un "Insertar después | Insertar antes".

Por ejemplo,

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertAfter(/configuration/system.web/authentication)">
  <deny users="?"/>
  <allow users="*"/>
</authorization>
un phu
fuente
17
Si usa VS2012, ahora hay una mejor solución. Vea a continuación stackoverflow.com/a/16679201/32055
Chris Haines
1
"InsertIfMissing" se insertará y reemplazará si es necesario?
Jessy
Prefiero esta opción sobre la otra gracias al uso de InsertAfter. InsertIfMissing no tiene sentido si está haciendo una eliminación de todos modos.
Shane Courtrille
125

En combinación con el xdt:Transform="Remove"uso xdt:Transform="InsertIfMissing"en VS2012.

<authorization xdt:Transform="Remove" />
<authorization xdt:Transform="InsertIfMissing">
  <deny users="?"/>
  <allow users="*"/>
</authorization>
ADW334034
fuente
¡Perfecto! Esto es lo que hemos estado esperando.
Chris Haines
9
Esto no funciona como solicitudes de OP, en absoluto.
BradLaney
2
La respuesta ha sido editada para demostrar más claramente cómo responde la pregunta original.
Bon
25
No lo entiendo Si lo elimina, por supuesto que faltará, es solo un Insert en ese punto, ¿verdad?
Chad Schouggins
66
@ChadSchouggins no necesariamente: la Removetarea solo elimina la primera aparición. Algunos elementos pueden tener múltiples ocurrencias. No puedo imaginar que quieras esto, pero luego eliminaría la primera aparición y omitiría la InsertIfMissingtarea. Pero habrías estado en lo correcto si él hubiera usado en su RemoveAlllugar.
Steven Liekens
89

Utilice la InsertIfMissingtransformación para asegurarse de que existe la configuración de la aplicación.
Luego use la Replacetransformación para establecer su 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>

También podría usar la SetAttributestransformación en lugar de Replace. La diferencia es que SetAttributesno toca los nodos secundarios.

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

Estas técnicas son mucho mejores que eliminar + insertar porque los nodos existentes no se mueven a la parte inferior de su nodo principal. Se agregan nuevos nodos al final. Los nodos existentes permanecen donde están en el archivo fuente.

Esta respuesta se aplica solo a las versiones más recientes de Visual Studio (2012 o más nuevas).

Steven Liekens
fuente
7

Un método mejor para mí fue insertar el elemento solo si no existe, ya que solo estoy configurando ciertos atributos. Eliminar el elemento descartaría cualquier otro atributo del elemento principal si existiera.

ejemplo: web.config (sin elemento)

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

web.config (con elemento)

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

Usando el localizador con una expresión XPath, agrego el nodo si no existe y luego establezco mi atributo:

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

ambos archivos web.config resultantes tienen includeExceptionDetailInFaults = "true" y el segundo conserva el atributo httpsHelpPageEnabled donde el método remove / insert no lo haría.

Dan
fuente
1
Me gusta esta idea, pero recibo un error si el elemento ya existe "Ningún elemento en el documento fuente coincide ...". Es decir, si existe, el "no" está fallando, por lo que es un error.
goodeye
Esta es la técnica que necesita cuando usa versiones de XDT que no admiten el nuevo elemento (ish) "InsertIfMissing".
IanBru