Archivos app.config / web.config específicos del desarrollador en Visual Studio


93

Tenemos varios proyectos .NET donde almacenamos ciertas configuraciones en archivos de configuración.

Ahora, cada desarrollador tendrá sus propios archivos de configuración que difieren un poco (diferentes cadenas de conexión para conectarse a bases de datos locales, diferentes puntos finales WCF , etc.)

Por el momento, solemos revisar los archivos app / web.config y modificarlos para adaptarlos a nuestras necesidades.

Esto genera muchos problemas, ya que de vez en cuando alguien verifica su propia configuración o pierde la configuración personalizada al obtener la última versión de TFS .

¿Cómo afrontas situaciones como esta? ¿O no tienes este problema en absoluto?


10
Voto para reabrir, ya que este es un problema común para los desarrolladores de estudios visuales e involucra directamente las herramientas que los desarrolladores están usando. (de ahí los votos)
Christian Gollhardt

De acuerdo, este es un problema persistente ya que el tamaño de nuestro equipo ha crecido y varios intentos de resolverlo han sido insatisfactorios.
DiskJunky

Respuestas:


66

Usamos un sistema que combina varias de las respuestas existentes en esta página y se basa en esta sugerencia de Scott Hanselman .

En resumen, lo que hicimos fue tener una app.config / web.config común y tener la mayoría de las configuraciones específicas en archivos individuales, como lo sugieren otras respuestas aquí. por ejemplo, para nuestra configuración SMTP, el archivo app.config contiene

<system.net>
  <mailSettings>
    <smtp configSource="config\smtp.config" />
  </mailSettings>
</system.net>

Este archivo está en control de código fuente. Sin embargo, los archivos individuales, como este, no son:

<?xml version="1.0" encoding="utf-8" ?>
<smtp deliveryMethod="Network">
  <network host="127.0.0.1" port="25" defaultCredentials="false" password="" userName ="" />
</smtp>

Sin embargo, ahí no es exactamente donde termina la historia. ¿Qué pasa con los nuevos desarrolladores o una instalación de fuente nueva? La mayor parte de la configuración ya no está en el control de código fuente, y es complicado crear manualmente todos los archivos .config que necesitan. Prefiero tener una fuente que al menos se compile de inmediato.

Por lo tanto, mantenemos una versión de los archivos .config en el control de código fuente, denominada archivos .config.default . Por lo tanto, un árbol de origen fresco se ve así:

texto alternativo

Aún así, no es realmente útil para el desarrollador, ya que para Visual Studio son solo archivos de texto sin sentido. Por lo tanto, el archivo copy_default_config.batpor lotes`` se encarga de crear un conjunto inicial de archivos .config a partir de los archivos .config.default:

@echo off
@REM Makes copies of all .default files without the .default extension, only if it doesn't already exist. Does the same recursively through all child folders.
for /r %%f in (*.default) do (
    if not exist "%%~pnf" (echo Copying %%~pnf.default to %%~pnf & copy "%%f" "%%~pnf" /y)
)
echo Done.

El script se puede volver a ejecutar de forma segura, ya que los desarrolladores que ya tienen sus archivos .config no los sobrescribirán. Por lo tanto, uno podría posiblemente ejecutar este archivo por lotes como un evento previo a la compilación. Los valores de los archivos .default pueden no ser exactamente correctos para una nueva instalación, pero son un punto de partida razonable.

En última instancia, cada desarrollador termina con una carpeta de archivos de configuración que se parece a esto:

texto alternativo

Puede parecer un poco complicado, pero definitivamente es preferible a la molestia de que los desarrolladores se pidan unos a otros.


¿Por qué no tener directamente el .config principal en el repositorio pero no los individuales?
graffic

6
Qué dolor, necesitamos una mejor solución para esto. Tenía un método similar configurado y me cansé de que fuera tan frágil y todavía necesitara una explicación para los nuevos desarrolladores.
jpierson

@Gavin, aparece un error si trato de ejecutar el archivo bat que ha descrito: ' @ echo' no se reconoce como un comando interno o externo, programa operable o archivo por lotes.
Austin

2
@Austin, parece que tiene algo de basura no imprimible antes de '@echo', parte de la cual es posible la marca de orden de bytes Unicode? Tal vez algo salió mal al copiar / pegar, o el archivo por lotes está guardado en una codificación que no se puede leer correctamente.
Gavin

21

En su Web.config use la fuente de otros archivos

<configuration>
    <connectionStrings configSource="ConnectionStrings.config" />
...
</configuration>

Mantenga web.config en control de versiones y no lo haga para ConnectionStrings.config. Ahora todos los desarrolladores tienen un archivo para la cadena de conexión.

Puede hacer esto para todas las configuraciones que dependen de la localidad.


1
Esto funcionó muy bien para mí. Consulte también: davidgiard.com/2012/05/25/… El archivo ConnectionStrings.config debe estar en la misma carpeta que la aplicación o la configuración web. Además, debe cambiar sus propiedades a 'copiar si es más reciente' para la salida. Y el archivo ConnectionStrings.config necesita la sección completa con elementos de apertura y cierre. También debe configurar el control de versiones para ignorar el archivo, de modo que cada uno sea específico del usuario.
Jeffrey Roughgarden

1
Usé la opción <appSettings file = ".."> ya que tuve que fusionar configuraciones
Spikolynn

1
@JeffreyRoughgarden Si incluye el archivo ConnectionStrings.config en el Explorador de soluciones, ¿el archivo no tiene que existir en el sistema de archivos? Y si lo hace, significa que lo ha registrado en el control de fuente. Cuál es el problema inicial del que estábamos tratando de escapar.
Jez

20

Aquí una solución para archivos web.config y Visual Studio 2010:

1) Edite manualmente el archivo .csproj de su aplicación web para agregar un AfterBuilddestino como este:

  <Project>
   ...
    <Target Name="AfterBuild">
      <Copy SourceFiles="web.config" DestinationFiles="obj\$(Configuration)\tempweb.config" />
      <TransformXml Source="obj\$(Configuration)\tempweb.config"
                  Transform="web.$(USERNAME).config"
                  Destination="obj\$(Configuration)\tempweb2.config" />
      <ReadLinesFromFile File="obj\$(Configuration)\tempweb2.config"><Output TaskParameter="Lines" ItemName="TransformedWebConfig"/></ReadLinesFromFile>
      <ReadLinesFromFile File="web.config"><Output TaskParameter="Lines" ItemName="UnTransformedWebConfig"/></ReadLinesFromFile>
      <Copy Condition=" @(UnTransformedWebConfig) != @(TransformedWebConfig) " SourceFiles="obj\$(Configuration)\tempweb2.config" DestinationFiles="web.config" OverwriteReadOnlyFiles="True" />
    </Target>
  </Project>

Este destino transformará el archivo Web.config correspondiente al desarrollador actual que inició sesión, de ahí la $(USERNAME)variable, con el archivo correspondiente creado en 1). Reemplazará el Web.config local solo si el contenido ha cambiado (para evitar reiniciar) en cada compilación, incluso si el Web.config local está controlado por fuente, es por eso que OverwriteReadOnlyFilesestá establecido en True. De hecho, este punto es discutible.

2) Cree un archivo con el nombre Web.[developer windows login].configde cada desarrollador del proyecto. (por ejemplo, en las siguientes capturas de pantalla tengo dos desarrolladores llamados smo y smo2):

ingrese la descripción de la imagen aquí

Estos archivos (1 por desarrollador) pueden / deben ser controlados por fuente. No deben marcarse como dependientes del Web.config principal porque queremos poder verificarlos individualmente.

Cada uno de estos archivos representa una transformación para aplicar al archivo Web.Config principal. La sintaxis de transformación se describe aquí: Web.config Sintaxis de transformación para la implementación de proyectos de aplicaciones web . Reutilizamos esta genial tarea de transformación de archivos Xml que viene lista para usar con Visual Studio. El propósito de esta tarea es combinar elementos y atributos Xml en lugar de sobrescribir todo el archivo.

Por ejemplo, aquí hay una muestra web.[dev login].configque cambia una cadena de conexión llamada 'MyDB', independientemente del resto del archivo Web.config:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <connectionStrings>
      <add name="MyDB" 
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
    </connectionStrings>
</configuration>

Ahora bien, esta solución no es perfecta porque:

  • después de la construcción, los desarrolladores pueden tener un Web.Config diferente localmente que en el sistema de control de código fuente
  • es posible que tengan que forzar la escritura local cuando obtengan un nuevo Web.Config desde el sistema de control de fuente
  • los desarrolladores no deben consultar / en el web.config principal. Debe reservarse para pocas personas.

Pero al menos, solo tiene que mantener un archivo web.config principal único más un archivo de transformación por desarrollador.

Se podría adoptar un enfoque similar para los archivos App.config (no web), pero no di más detalles.


Cambié el nombre de mi Web.config a Web.base.config, creé un nuevo archivo Web.config, luego cambié de <Copy SourceFiles = "web.config"> a <Copy SourceFiles = "web.base.config" en el paso 1. Al hacer esto, puedo tener un web.config local que se puede ignorar en el control de fuente.
S. Baggy

Esto todavía no es ideal, pero lo prefiero a la otra solución
JMK

¿Crees que es posible utilizar un web.default.configcuando web.$(USERNAME).configno existe? Gracias por cierto por esta gran respuesta.
Christian Gollhardt


0

¿Qué tal si ignoras el archivo para que nunca se registre? Me encontré con un problema similar y agregué web.config a la lista de ignorados en Subversion.

Sin embargo, en TFS es un poco más difícil, vea esta publicación sobre cómo hacerlo.


0

Una forma de hacer frente es tener un sistema tokenizado y usar un script de rake para cambiar los valores.

Un método más rudimentario podría ser tener un enlace a un archivo AppSettings.config para todos los AppSettings en su web.config (similar con conexiones) es decir

<appSettings configSource="_configs/AppSettings.config" />

Luego tenga una carpeta con cada uno de sus desarrolladores que tenga una versión en una subcarpeta (es decir, / _configs / dave /). Luego, cuando un desarrollador está trabajando en su propio código, lo copia de la subcarpeta a la raíz de la carpeta vinculada.

Deberá asegurarse de comunicar los cambios a estos archivos (a menos que los tokenice). Si mantiene el archivo AppSettings.config fuera del control de la fuente y solo registra las carpetas individuales de los desarrolladores (todas), entonces se verán obligados a copiar la correcta.

Prefiero la tokenización, pero puede ser más difícil de poner en marcha si esto solo pretende ser una solución rápida.


0

Ignore los archivos y tenga un Commom_Web.Config y Common_App.Config. Usar un servidor de compilación de integración continua con tareas de compilación que cambian el nombre de estos dos a nombres normales para que el servidor de compilación pueda hacer su trabajo.


esto debe hacerse en máquinas de desarrollo, antes de que vaya a compilar el servidor
twarz01

No, este cambio de nombre debería ocurrir en el servidor de compilación. Los archivos de configuración comunes que se almacenan en la subversión son independientes de un desarrollador específico. Mientras que cada desarrollador ejecuta sus archivos de configuración personales para desarrollar en su máquina, y no se preocupa de enviarlos porque no es parte de la subversión.
Arthis

Lo que esto no admite es que los desarrolladores depuren la aplicación. La raíz web.configde la carpeta de origen se utiliza durante la depuración. Si, por ejemplo, añadido web.configa .gitignore, y sea requerido a los usuarios copiar Commom_Web.Configa web.configy editarlo a su fantasía, que está parte del camino. Pero luego, cuando necesita editar algo que es igual en todas las máquinas del desarrollador, como la system.web/compilationsección o particular appSettingsque debería ser el mismo en todas partes, este esquema se desmorona.
binki

0

Tenemos el mismo problema y lo que estamos haciendo es

  • Compruebe en web.config con los valores de testserver / production
  • El desarrollador va al explorador de Windows y cambia el modo de solo lectura del archivo
  • Edite la configuración para adaptarla a su entorno.
  • El registro en web.config ocurre solo cuando los valores de implementación cambian o se agrega o elimina cualquier entrada de configuración.
  • Esto necesita una buena cantidad de comentarios para cada entrada de configuración, ya que cada desarrollador debe cambiarla

1
Esto puede funcionar mejor en tiendas donde el control de código fuente que usa establece campos como Solo lectura por defecto, pero para otros que usan Subversion puede que no funcione tan bien. Podríamos establecer permisos de solo lectura en el repositorio para evitar que se confirme, sin embargo, eso debería establecerse en cada archivo de configuración para cada rama.
jpierson

Para aquellos de nosotros que no usamos algo como TFS, no es obvio cómo podría funcionar esta solución. ¿Podría darnos un poco más de antecedentes? Además, ¿no requiere que los desarrolladores tengan cuidado y no verifiquen accidentalmente el archivo?
binki

-1

Suponiendo que está usando Visual Studio, ¿por qué no usa diferentes configuraciones de solución? Por ejemplo: puede tener una configuración de depuración que use Web.config.debug y una configuración de versión que use Web.config.release. Web.config.debug debería tener algo como

<appSettings file="C:/Standard_Path_To_Configs/Standard_Name_For_Config.config"> 

con el archivo Standard_Name_For_Config.config que tiene todas las configuraciones personales del desarrollador, mientras que Web.config.release siempre tiene las configuraciones de producción. Puede almacenar configuraciones predeterminadas en alguna carpeta controlada por fuentes y hacer que un nuevo usuario las tome desde allí.


Entonces, cada usuario individual que alguna vez contribuiría al proyecto necesitaría tener su propia configuración de compilación. Esto no parece escalar y no apoya proyectos que aceptan contribuciones.
binki
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.