Preparar ficheros de configuración para diferentes entornos en ASP.NET Core 2
Aunque el sentido común es nuestra principal recomendación, no está de más recordar algunas de estas recomendaciones cuando estamos programando nuestras aplicaciones.
Hablando de ASP.NET Core en particular, pero ampliándolo de forma genérica, nunca debemos poner en los ficheros de configuración, y menos aún cuando son textos planos, información sensible que pueda poner en riesgo el proyecto, como contraseñas, etc.
Obviamente, poner esa información dentro del repositorio de código, tampoco es una de las mejores prácticas como podemos entender.
Sin embargo, el equipo debe probar de forma unitaria lo que programa, y de forma global o integrada el entorno y sus partes, y realmente es necesario disponer de un entorno de pruebas homogéneo e igual para todos, de forma que las pruebas den siempre los mismos resultados (esperados o inesperados) y no otros diferentes a cada persona que lo prueba, o momento en el que realizamos las pruebas.
Lo más habitual, es encontrarnos con los entornos de Desarrollo (Dev), Producción (Pro) y Staging (Sta).
Luego, particularidades aparte, suele haber más entornos, como el de QA, Integración,… pero a veces estos confluyen en alguno de los tres anteriores.
Definamos como definamos el modo de trabajo en el cual el equipo debe encontrarse cómodo, lo importante es que tengamos claro que las variables de configuración deben estar protegidas a medida que más alto o importancia tiene el entorno.
Así, cuando estamos programando, lo lógico es disponer de un entorno de desarrollo que nos permita hacer nuestras pruebas, y jugar con los resultados.
Este entorno es el más cambiante y vivo de todo el proceso de desarrollo (Dev).
Si accedemos a las propiedades de nuestro proyecto ASP.NET Core 2 MVC en Visual Studio 2017, y en concreto vamos a la solapa Debug, veremos que la plantilla de ASP.NET Core 2 MVC, ha creado por nosotros una variable de entorno denominada:
- ASPNETCORE_ENVIRONMENT => Development
Dentro del proyecto, encontraremos un fichero appsettings.json, pero si vamos a la carpeta local, encontraremos otro fichero llamado appsettings.Development.json.
Imaginemos que tenemos dentro de nuestro fichero appsettings.json el siguiente contenido:
{ "Logging": { "IncludeScopes": false, "Debug": { "LogLevel": { "Default": "Warning" } }, "Console": { "LogLevel": { "Default": "Warning" } } }, "Contact": { "Address": "One Microsoft Way|Redmond, WA 98052-6399|Phone: 425.555.0100", "SupportDetails": { "Name": "Support:", "Mail": "Support@example.com" }, "MarketingDetails": { "Name": "Marketing:", "Mail": "Marketing@example.com" } } }
Si abrimos el archivo appsettings.Development.json, veremos que el contenido de este es:
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } } }
Si dentro de este archivo de configuración de desarrollo ponemos lo siguiente:
{ "Logging": { "IncludeScopes": false, "Debug": { "LogLevel": { "Default": "Warning" } }, "Console": { "LogLevel": { "Default": "Warning" } } }, "Contact": { "Address": "One Microsoft Way|Redmond, WA 98052-6399|Phone: 425.555.0100", "SupportDetails": { "Name": "OtherSupport:", "Mail": "Support@example.com" }, "MarketingDetails": { "Name": "OtherMarketing:", "Mail": "Marketing@example.com" } } }
Veremos que Name en SupporDetails y en MarketingDetails, es diferente.
Para que cargue una cosa o la otra, dentro de la clase Startup, y en concreto dentro del constructor de esta clase, deberemos indicar el siguiente código:
var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("mySettings.json", optional: false, reloadOnChange: true) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables();
Aquí, cabe destacar que estamos indicando que la configuración cargue el JSON de mySeetings.json primero, luego el appsettings.json, y finalmente el appsettings.Development.json.
Tanto appsettings.json como appsettings.Development.json contienen las mismas variables, pero al poner uno después del otro, lo que estamos diciendo es que si existen las variables, sobreescriba las primeras con las segundas.
Es decir, el último definido es el que prevalece, y en nuestro caso es appsettings.Development.json.
De esta manera, el equipo completo podrá trabajar en las variables de appsettings.json, pero en realidad, cada desarrollador individualmente en local, podrá hacerlo sobre appsettings.Development.json.
Cuando llegue el momento de dar un paso adelante en el desarrollo y despliegue, deberemos definir o cambiar el nombre de la variable de entorno de acuerdo a nuestras necesidades.
Podemos hacer esto tan extensible como nos parezca oportuno.
Finalmente, indicar que la información de indicar la variable de entorno, la encontraremos dentro de la carpeta Properties del proyecto, y en el archivo launchSettings.json.
Lo más importante es ser flexible sin perder seguridad a la hora de trabajar con información o configuración sensible que nos pueda comprometer.
¡Happy Coding!