.net - deployonbuild - ¿Cómo implementar de manera condicional un app.config basado en la configuración de compilación?
msbuild publish (7)
Algo a lo largo de las líneas de
<PropertyGroup Condition="''$(Configuration)''==''Dev_Debug'' OR ''$(Configuration)''==''Dev_Release''" >
<CfgFileName>Dev</CfgFileName>
</PropertyGroup>
<!-- similar for Qs & Prd -->
<Target ...>...$(CfgFileName).config...
Tengo tres configuraciones de compilación personalizada {Dev, Qs, Prd}. Entonces, tengo tres configuraciones de aplicación {Dev.config, Qs.config, Prd.config}. Sé cómo editar el archivo .csproj para generar el correcto basado en la configuración de compilación actual.
<Target Name="AfterBuild">
<Delete Files="$(TargetDir)$(TargetFileName).config" />
<Copy SourceFiles="$(ProjectDir)$(Configuration).config" DestinationFiles="$(TargetDir)$(TargetFileName).config" />
</Target>
Mi problema es que necesito tener seis configuraciones de compilación {Dev, Qs, Prd} x {Debug, Release}. Necesito admitir la configuración de depuración y liberación (optimizaciones, pdb, etc.) para cada entorno. Sin embargo, los valores de configuración de la aplicación no cambian entre depuración / versión.
¿Cómo mantengo el script de construcción tan genérico como sea posible y uso solo las tres configuraciones de la aplicación? No quiero codificar demasiado muchas cadenas condicionales.
La última solución que me gustaría utilizar es crear 6 configuraciones de aplicaciones, 1 por configuración personalizada
{ Dev_Debug.config
, Dev_Release.config
, Qs_Debug.config
, ...
, Prd_Release.config
}.
Aunque, con esa configuración, podría mantener el script de compilación genérico, sin cadenas condicionales.
Solucionamos esto usando el elemento Elegir en el archivo csproj. Tenemos varias configuraciones diferentes configuradas, de modo que lo único que hacemos es soltar este bloque en su archivo proj y puede usar la configuración de VS para ayudarlo. Quiero secundar los consejos de Rob para pasar el app.config pasado. Me he estado moviendo en esa dirección por un tiempo.
<Choose>
<When Condition=" ''$(Configuration)'' == ''Debug'' ">
<ItemGroup>
<None Include="App.config" />
<None Include="Release/App.config" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<None Include="Release/App.config">
<Link>App.config</Link>
</None>
</ItemGroup>
</Otherwise>
Sugiero que su pregunta revele que ha superado la app.config
Es hora de pasar a una solución mejor y comenzar a abordar algunos problemas relacionados.
Por un lado, NUNCA debe implementar automáticamente un archivo de configuración en producción, y debe esperar que el personal de soporte de operaciones rechace con vehemencia cualquier intento de hacerlo. Por supuesto, si usted es el personal de soporte de operaciones, entonces debe rechazarlo usted mismo. En su lugar, su versión debe incluir algunas instrucciones para actualizar manualmente el archivo de configuración, con una muestra para ilustración. La configuración de producción es demasiado importante para medidas menores, a menos que simplemente no valore mucho su sistema de producción.
Del mismo modo para entornos de prueba y otros, pero en menor grado, por lo que realmente solo necesita su app.config
poblada para su propio trabajo de desarrollo.
Una opción es insertar las configuraciones múltiples en una única app.config
, que es razonable para aplicaciones pequeñas, relativamente poco importantes o en etapas tempranas de desarrollo / publicación. Por ejemplo, cree una configuración llamada algo así como target-env
que contenga un valor que use en su código para seleccionar otras configuraciones, por ejemplo, anteponiendo el valor a las teclas de las otras configuraciones.
Mi preferencia es pasar completamente app.config
o usarlo mínimamente. En este caso, prefiero poner solo los datos de configuración suficientes en un archivo para permitir que mi aplicación / sistema se conecte a su (s) base (es) de datos, luego coloco los detalles de configuración restantes en una tabla de base de datos especial para ese propósito. Esto tiene muchas ventajas, como hacer que la base de datos "sepa" qué entorno representa (desarrollo, prueba, producción, etc.) y mantener la configuración y los demás datos en conjunto. El paquete de implementación puede entonces mantenerse en secreto con respecto a las configuraciones y las diferencias de entorno: el código solo accede a sus datos de configuración y actúa en consecuencia, por lo que el mismo paquete de implementación es bueno para cualquier entorno.
Sin embargo, un factor clave para el éxito de este enfoque es que su código de aplicación debe "saber" lo que espera de la configuración y debe "saber" rechazar una configuración incorrecta / incompleta. Aquí es donde deberías pasar tu tiempo, sin intentar app.config
los límites de app.config
.
Eso generalmente significa crear su propia clase para acceder a los datos de configuración, y luego usar esa clase en su aplicación en su lugar. Esto también genera muchos otros beneficios, como datos de configuración fuertemente tipados: en lugar de String
, devuelve un DateTime
, o una Url
, o un Integer
, o una Currency
, o lo que mejor se ajuste a los datos de configuración y la aplicación.
Aquí hay una buena discusión en scott Hanselmans sobre la automatización de la configuración múltiple.
En la sección de comentarios hay algunas soluciones alternativas. Algunos interesantes como trabajar con delta de los archivos de configuración. Algunos otros son como tener diferentes archivos de configuración para diferentes entornos.
¿Qué hay de usar un servidor de compilación?
Ha pasado mucho tiempo desde que trabajé en .NET pero ¿no puedes usar el servidor Hudson (similar) para administrar tus configuraciones de compilación? ¿No es más fácil?
¿Y qué hay de NAnt? ¿No se ajusta a tus necesidades?
parece que esta es una solución más "moderna" (Disponible desde vs2010) http://blogs.msdn.com/b/webdevtools/archive/2009/05/04/web-deployment-web-config-transformation.aspx