web-config - visual - web.config transform connection string example
Transformación XDT: InsertBefore-Se ignora la condición del localizador (1)
Tengo un archivo web.config en el que necesito insertar el elemento <configSections />
o manipular los hijos de ese nodo si ya existe.
Si ya existe, no quiero volver a insertarlo (obviamente, ya que solo se permite una vez).
Normalmente, eso no sería un problema, sin embargo:
Si este elemento está en un archivo de configuración, debe ser el primer elemento secundario del elemento.
Entonces, si uso xdt:Transform="InsertIfMissing"
el elemento <configSections />
siempre se insertará después de cualquier elemento secundario existente (y siempre hay alguno), lo que viola la restricción anterior de tener que ser el primer elemento secundario de <configuration />
Intenté hacer este trabajo de la siguiente manera:
<configSections
xdt:Transform="InsertBefore(/configuration/*[1])"
xdt:Locator="Condition(not(.))" />
Lo que funciona a la perfección, si el elemento <configSections />
aún no existe. Sin embargo, la condición que he especificado parece ser ignorada.
De hecho, he probado algunas condiciones como:
Condition(not(/configuration[configSections]))
Condition(/configuration[configSections] = false())
Condition(not(/configuration/configSections))
Condition(/configuration/configSections = false())
Finalmente, por desesperación, intenté:
Condition(true() = false())
Todavía inserta el elemento <configSections />
.
Es importante tener en cuenta que estoy tratando de incluir esto en un paquete de NuGet, por lo que no podré usar una transformación personalizada ( como la que usa AppHarbor ).
¿Hay alguna otra forma inteligente de colocar mi elemento en el lugar correcto solo si aún no existe?
Para probar esto, use el comprobador de transformación de configuración de AppHarbors . Reemplace el Web.config con lo siguiente:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="initialSection" />
</configSections>
</configuration>
Y Web.Debug.config con lo siguiente:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<configSections
xdt:Transform="InsertBefore(/configuration/*[1])"
xdt:Locator="Condition(true() = false())" />
<configSections>
<section name="mySection" xdt:Transform="Insert" />
</configSections>
</configuration>
El resultado mostrará dos elementos <configSections />
, el primero que contiene "mySection", como se especifica en la transformación InsertBefore. ¿Por qué no se tuvo en cuenta la condición del localizador?
Entonces, después de enfrentar el mismo problema, se me ocurrió una solución. No es bonito ni elegante, pero funciona. (Al menos en mi máquina)
Acabo de dividir la lógica en 3 declaraciones diferentes. Primero, agrego un configSections vacío en la posición correcta (primero). Luego inserto la nueva configuración en las últimas configuraciones, que sería la nueva si es la única, o una existente de lo contrario. Por último, elimino cualquier elemento de configuración vacío que pueda existir. Estoy usando RemoveAll sin una buena razón, probablemente deberías usar Remove.
El código general se ve así:
<configSections xdt:Transform="InsertBefore(/configuration/*[1])" />
<configSections xdt:Locator="XPath(/configuration/configSections[last()])">
<section name="initialSection" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</configSections>
<configSections xdt:Transform="RemoveAll" xdt:Locator="Condition(count(*)=0)" />
La pregunta que sigue sin respuesta es por qué las condiciones del localizador no se tienen en cuenta para InsertBefore. O por qué no puedo manejar un conjunto de coincidencias vacío para InsertBefore, porque eso me permitiría hacer cosas divertidas como
//configuration/*[position()=1 and not(local-name()=''configSections'')]
Lo que para ser honesto es una forma mucho más clara de hacer lo que quiero lograr.