.NET Config Files configSource fuera de la carpeta del directorio de la aplicación

82

Tengo dos aplicaciones, una de consola y la otra de ASP.NET. Ambos necesitan conocer el mismo appSettings y connectionStrings. Entonces, idealmente, me gustaría usar la propiedad configSource de los archivos app.config / web.config para apuntar a una ubicación central. Por ejemplo

<connectionStrings configSource="D:\connectionStrings.config"/>
<appSettings configSource="D:\appSettings.config"/>

Eso sin embargo falla con un error:

El atributo configSource no es válido .: configSource 'D: \ appSettings.config' no es válido. Debe hacer referencia a un archivo en el mismo directorio o en un subdirectorio que el archivo de configuración.

¿Hay alguna forma de seguir usando los administradores de configuración appSettings / connectionStrings y obtener los valores de una ubicación externa?
Estoy feliz de tener que agregar código para hacerlo, pero no quiero tener que reemplazar todo el sistema del administrador de configuración.

Robert MacLean
fuente

Respuestas:

103

Otra solución es simplemente agregar el archivo de configuración en todos sus proyectos como un enlace en lugar de copiar el archivo a sus proyectos. Luego, configure la "Acción de compilación" del archivo en "Contenido" y "Copiar en el directorio de salida" en "Copiar si es más reciente" y cuando compile el proyecto tendrá el archivo en el directorio de salida.

Para agregar el archivo como un vínculo en el cuadro de diálogo "Agregar elemento existente", hay un botón Agregar con un menú desplegable. Elija "Agregar como enlace" en el menú desplegable del botón Agregar para completar el proceso.

Comunidad
fuente
agradable - mucho más fácil de entender para la gente que a mi manera
Robert MacLean
10
hola, me gusta esta respuesta y he intentado aplicarla a mi propio proyecto, y todo parece funcionar bien cuando "publico" mi aplicación (db.config se copia en el webroot como dijiste), pero no al depurar a través de VS Y Cassini. En su lugar, aparece una excepción "No se puede abrir el archivo configSource 'db.config'". ¿Hay algo que me falta para poder hacer esto? ¡Gracias!
Funka
16
Por supuesto, solo después de decidir romper y publicar un comentario pidiendo ayuda, lo soluciono inmediatamente después. Noté que mi db.config también está copiado en la carpeta / bin /, así que actualicé mi web.config para anteponer esta ruta en su configSourcey todo parece estar bien. ¡Gracias de nuevo!
Funka
1
@Funka: compruebe si tiene el problema porque la propiedad "Acción de compilación" de su db.config está configurada en "Ninguno" en lugar de "Contenido" como el web.config predeterminado. Creo que la configuración debería ser "Acción de compilación" = "Contenido" y "Copiar al directorio de salida" = "No copiar".
bopapa_1979
1
Esto no parece funcionar al depurar en VS 2013. Probé la solución Erics y esto tampoco funcionó.
Chris Nevill
16

Parece que así es. configSource debe estar en la misma carpeta o más.

Usted podría , aunque no estoy seguro de que debe , utilizar un enlace duro NTFS. [sonrisa loca]

Iain M Norman
fuente
10

Visual Studio 2015

Si tiene este problema con Web.Config, la respuesta aceptada es correcta, pero solo para expandir, ya que esto me hizo darme la palma de la mano:

Cuando agrega un archivo .config a su proyecto usando 'Agregar como enlace' y luego establece la propiedad Copiar del enlace en 'Copiar si es más reciente' o 'Copiar siempre', entonces el archivo físico se copiará en la carpeta / bin.

Por lo tanto, cuando tiene una sección de configuración definida en Web.Config como esta:

 <section name="mySpecialConfig" type="System.Configuration.AppSettingsSection" requirePermission="false" />

entonces debes definir el elemento de configuración relacionado así:

  <mySpecialConfig configSource="bin\MySpecialConfig.config">
  </mySpecialConfig>

de manera que configSource apunte al archivo físico bin \ MySpecialConfig.config, no al enlace. Además, tenga en cuenta que la ruta es una ruta física relativa .

Eso puede parecer ridículamente obvio, pero si no lo ha hecho antes, el archivo físico aún no está en la carpeta \ bin, por lo que es posible que no haga clic de inmediato.

Serexx
fuente
8

Puede cargar la configuración desde una ubicación arbitraria, pero no estará disponible a través de las propiedades estáticas de ConfigurationManager:

Configuration myConfig = ConfigurationManager.OpenExeConfiguration(path)

(Existe una sobrecarga que permite especificar archivos múltiples para admitir la jerarquía predeterminada / usuario-itinerante / usuario-local).

La pérdida de las propiedades estáticas significa que todo el código debe conocer las diferentes configuraciones.

Ricardo
fuente
Esto requiere que se cargue todo el archivo de configuración. Solo necesito que appSettings y connectionStrings sean iguales, el resto del archivo es diferente para cada aplicación, por lo que no resuelve el problema.
Robert MacLean
Toda la configuración se carga con las propiedades normales (estáticas) de todos modos, por lo que esto no hace una diferencia real.
Richard
Además, puede usar su propio formato XML y agregar su nombre a los archivos de configuración de las aplicaciones y leerlo directamente.
Richard
5

En el caso de las cadenas de conexión, es posible apuntar a un archivo compartido. Si el archivo compartido está en una red UNC, requiere privilegios administrativos en la máquina donde se alojará la aplicación.

Solución: en su web.config, use configSource para apuntar a un archivo de configuración local. Debido a las restricciones de .Net, esto debe estar en o por debajo del nivel del archivo de configuración raíz. Solo apunto a un archivo en la carpeta de la aplicación:

<connectionStrings configSource="ConnectionStrings.config" />

En una ubicación compartida a la que pueda acceder el usuario del grupo de aplicaciones, agregue el archivo de configuración que contiene las cadenas de conexión compartidas. Este archivo no debe contener ningún XML que no sea la propia sección connectionStrings. El archivo compartido, ConnectionStrings.config, se ve así:

<connectionStrings>
    <clear/>
    <add name="connString1" connectionString="connString1 info goes here"/>
    <add name="connString2" connectionString="connString2 info goes here"/>
</connectionStrings>  

Ahora el truco. Cree un enlace simbólico de Windows en la carpeta de su aplicación que apunte al archivo de configuración compartido externo. Necesitará privilegios de administrador para hacer esto:

mklink ConnectionStrings.config \\someServer\someShare\someFolder\ConnectionStrings.config

Acabamos de burlarnos de .Net. El sistema de configuración utilizará la configuración configSource para buscar cadenas de conexión en un archivo local llamado ConnectionStrings.config. El enlace simbólico parece un archivo a .Net, y el enlace simbólico se resuelve en el archivo de configuración compartido.

Advertencias: los cambios en el archivo compartido no activan automáticamente un reinicio de la aplicación en .Net. En el caso de IIS, el sitio web o el grupo de aplicaciones deberá reiniciarse manualmente.

Debido a la necesidad de privilegios administrativos para crear el enlace simbólico, es posible que este enfoque no funcione para todos. Hay dos alternativas relacionadas que pueden funcionar si el archivo compartido está en la misma unidad lógica: enlaces físicos y uniones. Consulte esta discusión y esta discusión para obtener más información.

Scott
fuente
3

Puede colocar ambas configuraciones en machine.config y luego estarán disponibles para todas sus aplicaciones en el servidor.

Freggel
fuente
Es una opción, pero no quiero (necesito) la configuración disponible para otras aplicaciones en la máquina. Lo preocupante son las cadenas de conexión, tienen nombres bastante genéricos que pueden entrar en conflicto con otras aplicaciones.
Robert MacLean
2

La solución que encontré que funcionó mejor fue poner los archivos de configuración "compartidos" en archivos centrales y luego usar un evento de compilación previa en Visual Studio para copiarlos en una carpeta relativa de cada proyecto que lo necesitaba.

Robert MacLean
fuente
2

Tuve bastante lucha con este problema, pero encontré una buena solución aquí: ejecución de prueba con configuración externa

(Puede dirigir la ejecución de prueba para copiar archivos y directorios en el directorio de ejecución de prueba editando el archivo .testrunconfig).

Aunque por qué el proyecto de tipo de prueba unitaria puede obtener configuraciones de su propia app.config, pero no poder cargar archivos de configuración referenciados como una app.config normal, es algo desconcertante para mí. Lo llamaría un error porque esperaría que un proyecto de prueba app.config se comporte de la misma manera que se comporta el app.config de la aplicación, pero no lo hace.

marcel_g
fuente
1

Puede utilizar el fileatributo en lugar deconfigSource

Hay un buen artículo aquí al respecto.

Esto le permite especificar una ruta relativa como esta

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings file="..\..\..\..\..\..\ExternalFile.config"></appSettings>
</configuration>

La ruta es relativa al directorio de salida.

Luego, en ExternalFile.config, simplemente agrega la appSettingssección

<appSettings>
    <add key="SomeKey" value="alue"/>
</appSettings>
alexs
fuente