ASP.NET 5: Configuración

Una de las novedades de ASP.NET5 es su sistema de configuración. En versiones anteriores el sistema de configuración estaba muy atado al fichero web.config. En este fichero se guardaba tanto la configuración propia del programa (cadenas de conexión, appsettings o información adicional que suele estar en secciones de configuración propias) como información de configuración del propio runtime: tipo de seguridad, módulos a cargar, bindings de assemblies y un sinfin más de configuraciones.

En ASP.NET5 eso se ha simplificado mucho. Un tema importante es que ahora está claramente separada la configuración del framework que se realiza mayoritamente por código, la configuración del runtime que se delega en el fichero project.json y la configuración propia del programa que está en cualquier otro sitio. En este post nos centraremos solamente en la configuración propia del programa.

Configuración propia del programa (configuración de negocio)

La configuración propia toma la forma básica de un diccionario con claves que son cadenas y valores que son… cadenas. No tenemos una interfaz propia para cadenas de conexión o para las secciones propias de configuración. Para entendernos, sería como si todo fuesen appsettings. Es un mecanismo sencillo (si necesitas algo por encima de eso es fácil construirlo). El sistema por si mismo no nos ata a ningún formato de fichero (esa configuración puede estar en un json, un xml o lo que sea).

Aunque, es cierto, que el sistema de por si no nos ata a ningún esquema en concreto de nuestros datos, si queremos utilizar los métodos que son capaces de leer información automáticamente de un fichero, entonces si que debemos adaptarnos al esquema previsto, aunque es bastante ligero.

P. ej. esos tres ficheros contienen todos ellos la misma configuración:

  1.  
  2.   "smtp": {
  3.     "server": {
  4.       "user": "eiximenis",
  5.       "mail": "mail@domain.com"
  6.     },
  7.     "auth": {
  8.       "anonymous": "true"
  9.     }
  10.   }
  11. }

  1. <smtp>
  2.     <server>
  3.         <user>eiximenis</user>
  4.         <mail>mail@domain.com</mail>
  5.     </server>
  6.     <auth>
  7.         <anonymous>true</anonymous>
  8.     </auth>
  9. </smtp>

  1. [smtp:server]
  2. user=true
  3. mail=mail@domain.com
  4. [smtp:auth]
  5. anonymous=true

Los 3 ficheros definen las siguientes claves:

  • smtp:server:user –> Con valor “eiximenis”
  • stmp:server:mail –> Con valor “mail@domain.com
  • smtp:auth:anonymous –> Con valor “true”

En versiones anteriores esos 3 valores hubiesen ido, seguramente, en la sección<appSettings /> del web.config. La verdad es que usar el separador dos puntos (:) en las claves de appsettings es algo que ya era como un “estándard de facto”.

Para cargar esos ficheros usamos los métodos AddJsonFile(), AddXmlFile() o AddIniFile() del objeto ConfigurationBuilder, que se suele crear en el constructor de la clase Startup:

  1. public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
  2. {
  3.     // Setup configuration sources.
  4.     var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
  5.         //.AddJsonFile("config.json")
  6.         //.AddXmlFile("config.xml")
  7.         .AddIniFile("config.ini")
  8.         .AddEnvironmentVariables();
  9.     Configuration = builder.Build();
  10. }
  11.  
  12. public IConfiguration Configuration { get; set; }

El objeto Configuration básicamente expone un indexer para acceder a los valores de la configuración:

  1. var usermail = Configuration["smtp:server:user"];

Si quiero acceder a un valor de la configuración desde un controlador MVC puedo incorporar el objeto Configuration dentro del sistema de inyección de dependencias de asp.net 5:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3.     services.AddInstance<IConfiguration>(Configuration);
  4. }

Y ahora puedo añadir un parámetro IConfiguration a cada controlador que lo requiera.

El método GetConfigurationSection me devuelve otro IConfiguration pero cuya raíz es la clave que yo indique. Es decir dado el objeto Configuration que tenía si hago:

  1. var usermail = Configuration["smtp:server:user"];
  2. var smtpcfg = Configuration.GetConfigurationSection("smtp");
  3. var usermail2 = smtpcfg["server:user"];
  4. var servercfg = Configuration.GetConfigurationSection("smtp:server");
  5. var usermail3 = servercfg["user"];

Los valores de usermail, usermail2 y usermail3 son el mismo.

Configuración tipada

Este esquema de configuración es funcional y sencillo, pero a veces queremos usar objetos POCO para guardar nuestra propia configuración. Supongamos que tenemos la siguiente clase para guardar los datos del servidor:

  1. public class ServerConfig
  2. {
  3.     public string User { get; set; }
  4.     public string Mail { get; set; }
  5. }

Podemos mapear los datos que están en “smtp:server” con el siguiente código:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3.     services.Configure<ServerConfig>(Configuration.GetConfigurationSection("smtp:server"));
  4. }

Recuerda que GetConfigurationSection(“stmp:server”) me devuelve un IConfiguration que apunta directamente a esta clave y que por lo tanto tiene las dos claves “user” y “mail” que se corresponen con los nombres de las propiedades de la clase ServerConfig. Esta línea además incluye dentro del sistema de inyección de dependencias la clase ServerConfig así que ahora puedo inyectarla a cualquier controlador MVC que lo requiera:

  1. public HomeController(IOptions<ServerConfig> sc)
  2. {
  3.     var cfg = sc.Options;
  4.     var user = cfg.User;
  5. }

Observa, eso sí, que el parámetro no es un ServerConfig, si no un IOptions<ServerConfig> (eso es porque services.Configure incluye la interfaz IOptions<T> en el sistema de inyección de dependencias). Para acceder al objeto con la configuración usamos la propiedad Options.

Configuración anidada

Por supuesto el sistema soporta configuración anidada. Es decir, lo siguiente es correcto:

  1. public class SmtpConfig
  2.  {
  3.      public ServerConfig Server { get; set; }
  4.      public AuthConfig Auth { get; set; }
  5.  }
  6.  
  7.  public class ServerConfig
  8.  {
  9.      public string User { get; set; }
  10.      public string Mail { get; set; }
  11.  }
  12.  
  13.  public class AuthConfig
  14.  {
  15.      public string Anonymous { get; set; }
  16.  }

Y registrarlas de la siguiente manera:

  1. services.Configure<SmtpConfig>(Configuration.GetConfigurationSection("smtp"));

Y ahora podemos inyectar un  IOptions<SmtpConfig> en cualquier controlador que lo requiera:

  1. public HomeController(IOptions<SmtpConfig> sc)
  2. {
  3.     var cfg = sc.Options;
  4.     var user = cfg.Server.User;
  5. }

¡Sencillo y rápido!

Y hasta aquí este post sobre la configuración en ASP.NET5… espero que os haya resultado interesante!

Saludos!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *