Mayo de 2017

Volumen 32, número 5

Tecnología de vanguardia: ASP.NET Core para desarrolladores de ASP.NET

Por Dino Esposito | Mayo de 2017

Dino EspositoGran parte del entusiasmo por ASP.NET Core se centra en la experiencia multiplataforma que ofrece. Aunque este es un logro enorme, no es necesariamente una ventaja si es un usuario habitual de ASP.NET con una extensa base de código .NET 4.x y no tiene previsto abandonar el conocido servidor IIS ni el entorno de Windows. En este caso, ¿cuál es la propuesta de valor de ASP.NET Core para un desarrollador habitual de ASP.NET?

En un primer momento, la nueva plataforma podía parecer completamente diferente, como si alguien se hubiese llevado su queso a escondidas durante la noche. ASP.NET Core se ha renovado y rediseñado desde el principio, siguiendo prácticas más modernas. Ello podría o no aumentar su eficacia de programación y su capacidad para tratar las preocupaciones de los clientes. Nadie puede responder de manera realista a esa pregunta en su nombre. Esta columna pretender aclarar el fundamento de cualquier publicidad exagerada, prueba comparativa y foco tecnológico, y entrar en materia directamente. Si está satisfecho con la plataforma actual, ¿qué aspectos de ASP.NET Core pueden captar su atención?

Prácticas comunes diseñadas en el marco

Cuando los miembros del equipo de ASP.NET diseñaron el marco de ASP.NET original, tomaron la mayoría de los procedimientos recomendados de las páginas Active Server y los aplicaron en un nuevo marco. De este modo, también introdujeron muchos elementos nuevos, como código compilado y administrado, postbacks automáticos y controles de servidor. ASP.NET Core sigue el mismo patrón evolutivo.

Las prácticas de desarrollo comunes, como la carga inicial de datos de configuración, la inserción de dependencias, los paquetes NuGet, la autenticación basada en notificaciones y las mejoras de Razor, son características nativas del nuevo marco. El nuevo marco también presenta un procedimiento de inicio diferente, un middleware de solicitud-respuesta mucho más modular, e incluso una infraestructura ligeramente más flexible para definir controladores y vistas. ASP.NET Core también es un marco multiplataforma, que permite desarrollar aplicaciones y hospedarlas en Windows, macOS y Linux. En cierto modo, ASP.NET Core le fuerza a escribir código mejor, donde se aplican algunos niveles adicionales de separación de preocupaciones de manera predeterminada. No obstante, no es nada que no pueda conseguir actualmente con disciplina.

Para cualquier formato de desarrollo totalmente nuevo, ASP.NET Core es una opción excelente. Sin embargo, un marco completamente nuevo tiene algunos costos iniciales inevitables: Todos los miembros del equipo deben ser expertos. Además, todos deben ser, o convertirse en, expertos en el modelo de aplicaciones de controlador de vista de modelos (MVC). No todo lo que se puede etiquetar como desarrollo totalmente nuevo es completamente nuevo. Se aconseja la reutilización de fragmentos de código existente o, como mínimo, de las aptitudes existentes (es decir, conocimientos de seguridad o acceso a datos). ¿En qué medida es esto posible de manera práctica? Para tratar este objeto, ASP.NET Core se presenta en dos modos.

Modos de ASP.NET Core

En la Figura 1, se muestra el cuadro de diálogo de Visual Studio 2015 para crear un nuevo proyecto. (Básicamente, es el mismo en Visual Studio 2017).

Creación de un nuevo proyecto de ASP.NET Core en Visual Studio
Figura 1 Creación de un nuevo proyecto de ASP.NET Core en Visual Studio

La primera plantilla creará un proyecto clásico que no será de Core. Las otras dos plantillas pueden crear un proyecto de ASP.NET Core para un marco de .NET Framework diferente. Es la primera encrucijada que se encuentra en su viaje por el territorio inexplorado de ASP.NET Core.

Optar por el marco .NET Framework completo le proporciona acceso a cualquier biblioteca de clases de .NET existente, pero limita el hospedaje a Windows e IIS solamente. En la Figura 2 se resumen las diferencias.

Figura 2 Diferencias fundamentales entre los modos de ASP.NET Core

Framework Hechos
.NET Framework

Solo para ASP.NET MVC; no para WebForms

Nuevo entorno en tiempo de ejecución y nueva API de programación

Todas las bibliotecas orientadas a la versión seleccionada de .NET Framework 

Solo hospedaje de IIS

.NET Core

Solo para ASP.NET MVC; no para WebForms

Nuevo entorno en tiempo de ejecución y nueva API de programación

Solo bibliotecas de .NET Core

Hospedaje multiplataforma

Independientemente de la elección de .NET Framework, el uso de ASP.NET Core expone su código a un nuevo entorno en tiempo de ejecución que unifica el tiempo de ejecución de MVC basado en system.web con el tiempo de ejecución de Web API inspirado en los principios de OWIN.

Separación de IIS

En los últimos años, el marco Web API intentó satisfacer la alta demanda de servidores ligeros capaces de exponer una interfaz de RESTful a los clientes habilitados para HTTP. Web API desacopló el modelo de aplicaciones del servidor web e indujo a la especificación OWIN, un conjunto de reglas de servidor web y aplicaciones para interoperar. No obstante, Web API necesita un host y, si se hospeda en el contexto de una aplicación de ASP.NET, agrega otro entorno en tiempo de ejecución a la superficie de memoria. Esto sucede al mismo tiempo que el sector está cambiando a una web supersimple. Un servidor web mínimo y supersimple es un punto de conexión HTTP para obtener contenido lo más rápido posible, una fina capa HTTP en torno a alguna lógica de negocios. Todo lo que un servidor supersimple debe hacer es procesar la solicitud de manera adecuada y devolver una respuesta sin sobrecarga, excepto para la lógica de negocios.

Aunque en cierta medida es personalizable, el entorno en tiempo de ejecución de ASP.NET actual no se diseñó para tratar escenarios como este. La separación del entorno de ASP.NET del entorno de hospedaje es el principal cambio que encontrará en ASP.NET Core y el motivo de muchos cambios posteriores en el nivel de la aplicación.

Inicio de una aplicación

Después de crear un nuevo proyecto, lo primero que observará es la falta de un archivo global.asax y la presencia de un archivo program.cs. Por impactante que pueda ser, una aplicación de ASP.NET Core es una aplicación de consola normal que se inicia mediante la herramienta de controlador dotnet (bit.ly/2mLyHxe).

La herramienta dotnet es la clave de la compatibilidad multiplataforma. Cuando la herramienta de línea de comandos (y .NET Core Framework) esté disponible para una nueva plataforma, el hospedaje se reduce a la conexión del servidor web con la herramienta. En IIS, la publicación se logra a través de un módulo ad hoc, el paquete .NET Core Windows Server Hosting (bit.ly/2i9cF4d). En Apache, en un servidor de Ubuntu, se logra por medio de un archivo de configuración. Puede encontrar un ejemplo en bit.ly/2lSd0aF.

El servidor web real funciona como un proxy inverso y se comunica con la aplicación de consola a través de un puerto configurado. La aplicación de consola se compila en torno a otro servidor web más simple, que recibe solicitudes y desencadena la canalización de aplicaciones interna para su procesamiento. El código siguiente hace el trabajo:

var host = new WebHostBuilder()
  .UseKestrel()
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseIISIntegration()
  .UseStartup<Startup>()
  .Build();
Host.Run();

Kestrel es el nombre del servidor web de ASP.NET, que recibe solicitudes entrantes y las procesa a través de la canalización. La llamada al módulo de integración de IIS en el fragmento de código solo es necesaria si se hospeda en IIS.

Tener un proxy inverso en torno a la aplicación de ASP.NET Core se recomienda principalmente por motivos de seguridad, ya que el servidor web interno Kestrel no incluye (por ahora) filtros para evitar situaciones, tales como los ataques de denegación de servicio distribuido (DDoS). Desde un punto de vista meramente funcional, no es estrictamente necesario tener un proxy inverso habilitado.

Como ya mencionamos anteriormente, ya no existe ningún archivo global.asax en la aplicación de ASP.NET Core y el rol del archivo web.config disminuye extremadamente. En realidad, solo atiende al propósito de habilitar IIS para que actúe en nombre de la aplicación, por ejemplo, para proporcionar páginas de errores estáticos. Acciones importantes, como la configuración del control, el registro y la autenticación de errores, y el almacenamiento de datos de configuración globales se llevan a cabo a través de una nueva API que se organiza desde la clase Startup.

La clase Startup

La clase Startup contiene como mínimo un par de métodos a los que el host llamará durante la fase de inicialización:

public class Startup
{
  public void ConfigureServices(IServiceCollection services)
  public void Configure(IApplicationBuilder app)
  {
    app.Run(async (context) =>
    {
      await context.Response.WriteAsync(DateTime.Now)
    });
  }
}

A través del método ConfigureServices, se declaran los servicios del sistema que usará la aplicación. Técnicamente, el método es opcional, pero diría que se requiere uno en cualquier escenario realista. Para un desarrollador de ASP.NET tradicional, podría ser impactante averiguar que incluso el uso del modelo de aplicaciones MVC debe declararse y habilitarse de forma explícita. No obstante, este hecho indica con qué seriedad se toma la modularización en ASP.NET Core:

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc();
}

En el método Configure, se configuran los servicios solicitados anteriormente. Por ejemplo, si solicitó el servicio MVC de ASP.NET, en Configure puede especificar la lista de rutas admitidas. Tenga en cuenta que también necesita una llamada explícita a fin de habilitar el servidor web interno para que proporcione archivos estáticos, incluidos los archivos comunes como jQuery y Bootstrap:

public void Configure(IServiceCollection services)
{
  app.UseStaticFiles();
  app.UseMvcWithDefaultRoute();
  ...
}

En la clase Startup también se configura el middleware de la aplicación. El nuevo término "middleware" presenta una coincidencia conceptual considerable con los módulos HTTP del entorno ASP.NET actual. En ASP.NET Core, el middleware funciona como se muestra en la Figura 3.

Middleware de ASP.NET Core
Figura 3 Middleware de ASP.NET Core

Puede registrar fragmentos de código que tienen la posibilidad de preprocesar y posprocesar cualquier solicitud entrante, lo que significa que cada middleware puede registrar código que se ejecute antes o después del middleware de finalización (el método Run del método Configure de la clase Startup). El modelo general se parece al antiguo modelo ISAPI de IIS. A continuación, se incluye middleware de muestra:

app.Use(async (httpContext, next) =>
{
  // Pre-process the request
  // Yield to the next middleware
  await next();
  // Post-process the request   
});

Un middleware es una función que toma un objeto HttpContext y devuelve un objeto Task. La lista de componentes de middleware termina con el método Run. En comparación con la canalización de ASP.NET actual, la canalización de ASP.NET Core es bidireccional y totalmente personalizable. Además, está vacía de manera predeterminada.

Servicios web supersimples

Se entiende que, sin un método Run en la canalización, ninguna solicitud producirá jamás una respuesta. Al mismo tiempo, un método Run es todo lo que necesita para producir una respuesta. Esto muestra lo corta que puede ser la canalización en una aplicación de ASP.NET Core. En ASP.NET WebForms y MVC, suceden muchas cosas antes de que su código se ejecute para cada solicitud. Por ejemplo, la resolución de un método de controlador es un procedimiento bastante largo, que implica un subsistema completo centrado en el invocador de la acción. En su lugar, el método Run es una llamada directa que sigue inmediatamente a la recepción de la solicitud.

Supongamos que quiere crear un servidor de archivos que posea una lista de archivos de imagen (por ejemplo, marcas) y devuelva una imagen con el tamaño definido correctamente según algunos parámetros de entrada o las propiedades del dispositivo. En el entorno ASP.NET actual, la opción más rápida es probablemente escribir un controlador HTTP ad hoc (una clase que se crea mediante la implementación de la interfaz IHttpHandler asignada a una ruta URL fija). Un controlador HTTP es más rápido que un punto de conexión ASPX y la acción del controlador MVC debido a la canalización más fina. También tiene una superficie menor que un punto de conexión de API web, ya no que no requiere una segunda canalización de OWIN encima de la canalización de ASP.NET básica. (Este no es el caso cuando una solución API web se hospeda fuera de IIS).

En ASP.NET Core, la creación de un servidor de archivos eficaz es más fácil y más efectiva que nunca. Todo lo que tiene que hacer es diseñar la lógica adicional (es decir, el cambio de tamaño y la recuperación) y enlazarla al método Run del método ConfigureServices:

public void Configure(IApplicationBuilder app)
{
  app.Run(async (context) =>
  {
    var code = context.Request.Query["c"];
    var size = context.Request.Query["s"];
    var file = FindAndResizeFlag(code, file);
    await context.Response.SendFileAsync(file);
  });
}

En el ejemplo, supongo la existencia de alguna lógica personalizada para buscar un nombre de servidor de archivos que coincida con los parámetros proporcionados que, después, proporciono al llamador a través del objeto Response. No se requiere ningún otro código, visible ni invisible. Francamente, no podía ser más fácil.

Diga lo que diga su intuición sobre ASP.NET Core, tanto si es escéptico o entusiasta al respecto, ASP.NET Core proporciona una funcionalidad única que no encontrará en ninguna otra plataforma de ASP.NET: la creación de servicios web minimalistas y supersimples. Al mismo tiempo, la misma infraestructura que permite compilar servicios web supersimples es la mejor garantía de que cualquier solicitud se pueda atender con la mínima sobrecarga legítimamente posible.

Resumen

Para ser un desarrollador de ASP.NET Core productivo, solo tiene que estar familiarizado con un modelo de aplicaciones más moderno que WebForms: el modelo MVC de ASP.NET o el modelo de aplicaciones de una sola página. A pesar de las apariencias, la mayoría de los últimos cambios de ASP.NET Core se encuentran en el entorno en tiempo de ejecución. Comprender el modelo de hospedaje y el middleware es suficiente para dar sentido a la nueva plataforma. Al final, se sigue tratando de crear controladores y de representar vistas de Razor. Algunas tareas comunes, como la autenticación, el registro y la configuración, necesitarán una API diferente, pero su aprendizaje requiere poco tiempo. Tal como yo lo veo, el reto es encontrar qué puede ofrecerle.


Dino Esposito es el autor de "Microsoft .NET: Architecting Applications for the Enterprise" (Microsoft Press, 2014) y "Modern Web Applications with ASP.NET" (Microsoft Press, 2016). Como experto técnico para las plataformas .NET y Android en JetBrains y orador frecuente en eventos internacionales del sector, Esposito comparte su visión sobre el software en software2cents.wordpress.com y en su Twitter @despos.

Gracias al siguiente experto técnico de Microsoft por revisar este artículo: James McCaffrey