Nuevos mecanismos de ASP.NET Core
Introducción
La nueva versión de ASP.NET Core incorpora varios mecanismos nuevos que permiten a los desarrolladores gestionar mejor determinados aspectos de sus proyectos. En versiones anteriores, cuando el proyecto requería que las APIs se expusieran a través de la aplicación web, la pieza Web API ofrecía sus propias API y clases para exponer los servicios al mundo exterior. Por ejemplo, existía una clase base ApiController para las APIs y una clase Controller para las páginas de la aplicación, aunque la función de un controlador es siempre la misma: recuperar la petición HTTP, procesar los datos y devolver una respuesta.
Lo mismo ocurría con el acceso a los datos, que a menudo resultaba tedioso. El código de negocio estaba contaminado con varios bloques using para garantizar el cierre de la conexión con la base de datos. Sin duda, es una buena práctica cerrar la conexión lo antes posible, pero la legibilidad del código se resentía por ello. ASP.NET Core incorpora un nuevo sistema de dependencias para gestionar mejor este tipo de situaciones y aumentar la mantenibilidad del código de negocio.
En este capítulo se tratarán algunas novedades extremadamente prácticas del framework. En primer lugar, la siguiente sección tratará el tema de la inyección de dependencias para gestionar adecuadamente las dependencias...
Inyección de dependencia
La inyección de dependencias de ASP.NET Core es un conjunto de servicios y mecanismos preintegrados en el framework para inyectar servicios en toda la aplicación. En versiones anteriores, el desarrollador necesitaba un framework externo, pero esto ya no es necesario.
El principio de inyección de dependencias es una técnica que consiste en acoplar libremente objetos y clases de servicio entre sí y con sus dependencias. En lugar de instanciar los servicios directamente en los métodos a través de constructores o de using, la clase declarará qué dependencias necesita para funcionar. La mayoría de las veces, la clase declarará sus dependencias en su constructor: este proceso se denomina constructor injection y permite respetar las buenas prácticas llamadas Explicit Dependencies Principle. El objetivo es que la clase exponga explícitamente sus dependencias en el constructor.
Sin embargo, es importante diseñar la clase teniendo en cuenta el principio DI (Dependency Injection) y mantener los servicios débilmente acoplados a las dependencias. Otra buena práctica titulada Dependency Inversion Principle establece una frase que resume muy bien la filosofía DI:
"Los módulos de alto nivel no deben depender de los de bajo nivel; ambos deben depender de abstracciones".
Esta frase es muy reveladora del método que hay que adoptar al inyectar servicios en clases: hay que inyectar una abstracción de esta clase y no la clase en sí. En C#, esto equivaldría a declarar una interfaz como dependencia de la clase. Este principio de deportar dependencias a interfaces y proporcionar implementaciones concretas, también es un ejemplo del pattern de Strategy Design.
Cuando un sistema se diseña para utilizar inyección de dependencias, necesita un contenedor de dependencias para listar todos los servicios que potencialmente pueden inyectarse en las clases. Esto se conoce como contenedor de inversión de control o contenedor de inyección de dependencias. La inversión de control también es una buena práctica que invierte la responsabilidad de crear la instancia cuando se resuelven dependencias: el framework es el que decidirá qué instancia utilizar para una dependencia dada de un tipo dado.
La inyección de dependencia...
Middleware
Los middleware es un nuevo concepto introducido con ASP.NET Core como parte de la especificación Open Web Interface for .NET (OWIN). El objetivo de OWIN es desacoplar el servidor y la aplicación, manteniendo un estándar abierto y estimulando el ecosistema de código abierto de .NET Web. Estos son los términos clave definidos por OWIN:
-
Server: servidor HTTP que se comunica directamente con el cliente y utiliza la semántica de OWIN para realizar una serie de operaciones para procesar la solicitud.
-
Web Framework: conjunto de componentes, basados en OWIN y que exponen sus propios objetos y servicios, para facilitar el procesamiento de peticiones. A efectos de este capítulo, el Web Framework es ASP.NET Core.
-
Web Application: aplicación web construida sobre un Web Framework utilizando servidores compatibles con OWIN.
-
Middleware: conjunto de componentes por los que pasará una petición HTTP para realizar un tratamiento específico, modificar la ruta, definir la respuesta, etc.
-
Host: proceso en el que se ejecutan la aplicación y el servidor.
Por tanto, los middlewares son componentes (en concreto, son clases C#) que se encadenarán y que actuarán por turnos sobre la petición HTTP. Cada middleware decidirá si pasa o no la petición al siguiente middleware en función de la acción que acaba de realizar sobre la petición. Se utiliza un delegado de petición para construir la cadena de peticiones. Depende de cada middleware pasar a la siguiente a través de este delegado de petición o cortocircuitar el encadenamiento según sea necesario.
El middleware se configura en el método Configure de la clase Startup mediante los métodos de extensión Run, Map y Use.

Diagrama del encadenamiento de los middleware
La ventaja de cortocircuitar la petición por los middlewares es que evita procesamientos innecesarios. Si el usuario quiere acceder a una página que requiere autenticación y si el middleware detecta que el usuario no está autenticado, redirigirá automáticamente al usuario a la página de inicio de sesión, sin pasar el testigo al middleware siguiente.
En la plantilla por defecto de Visual Studio, el middleware preconfigurado es el siguiente:
-
El tratamiento de errores.
-
El módulo proxy inverso HttpPlatformHandler...
Web API
El protocolo HTTP no sólo permite devolver páginas HTML con CSS y JavaScript, sino también construir APIs que expongan servicios y datos. El objetivo de estas APIs no es sólo hacer accesibles determinados datos de su sitio web, sino también permitir que alguien ajeno a él interactúe con ellos, por ejemplo insertando registros o recuperando una lista de información. Lo importante es recordar que estas APIs permiten integrar puntos de entrada adicionales para el sistema.
ASP.NET Core ha simplificado el uso de las API mediante la unificación del framework. Hoy en día, un sitio web desarrollado con ASP.NET Core podrá devolver HTML y APIs conservando el mismo código básico y también el mismo pipeline HTTP.
Diagrama de unificación del framework
En la práctica, las API se representan simplemente mediante controladores MVC que tienen una ruta bastante distinta de las demás rutas convencionales. Sin embargo, hay que pensar bien cómo se organizan estos controladores, porque su uso no es el mismo. Un controlador de Web Pages responderá según un protocolo muy específico, que es /controller/action, por lo que son las acciones las que dictan qué vista se devolverá.
Los controladores de API responderán según el método HTTP utilizado, es decir, GET, POST, PUT o DELETE. Por ejemplo, la respuesta del API /api/product no será la misma si el método es GET o PUT. Por tanto, es importante diseñar las API en función de los métodos HTTP y no de las acciones que exponen. Por supuesto, siempre es posible exponer rutas particulares para las API en función de los requisitos. A modo de recordatorio, los métodos importantes son:
-
GET: recupera información en forma de entidad (lista o individual).
-
POST: creación de la entidad enviada al servidor.
-
PUT: actualizar y/o sustituir datos en la base de datos.
-
DELETE: elimina la entidad del servidor.
Tomemos el ejemplo de un conjunto de APIs que exponen servicios relacionados con la gestión de productos. Las API a crear tendrían el siguiente aspecto:
API |
Descripción |
GET /api/product |
Recuperación de todos los productos |
GET /api/product/{id} |
Recuperación de productos por ID |
POST /api/product |
Añadir... |
API mínimas
En un sector en rápida evolución, surgen nuevos conceptos en arquitectura y prácticas de desarrollo. Uno de estos conceptos es el microservicio, es decir, el desarrollo de una aplicación mínima, dirigida a un dominio empresarial concreto, con su propia base de datos y exponiendo solo las API necesarias para gestionar ese dominio.
En respuesta a la creciente demanda de este tipo de desarrollo, los equipos de Microsoft han introducido la posibilidad de crear aplicaciones web ASP.NET Core con la mínima cantidad de código necesaria para crear APIs.
El código que se muestra a continuación es suficiente para ejecutar la aplicación y expone un API que devuelve una cadena de caracteres. En este caso concreto, el desarrollador no necesita pasar por todas las carpetas y archivos que tradicionalmente componen una aplicación Web API (como las carpetas Controllers y Areas, por ejemplo).
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
La línea WebApplication.Create se encargará de añadir todas las capas necesarias para que la aplicación funcione correctamente: enrutamiento, inyección de servicios, gestión de controladores, gestión de la configuración, etc. Lo único que tiene que hacer el desarrollador es definir sus rutas mediante el método MapGet y, a continuación, lanzar la aplicación mediante el método Run.
Para crear APIs, existen varios métodos que siguen la misma semántica en función del método HTTP requerido:...