Fala galera, beleza?
Uma das novidades mais bacanas do ASP.NET 5 é a forma como ele trabalha com Middlewares. Abaixo vamos entender um pouco o que são, de onde vem, o que comem como funcionam e como implementar Middlewares para nossas aplicações ASP.NET 5.
Como tudo isso pode ser muita informação, vamos por partes e aos poucos. Futuramente elaborarei mais artigos explicando mais aspectos referentes ao trabalho com Middlewares, bem como mostrando algumas ferramentas que expostas através de Middlewares e que podem ajudar no desenvolvimento de nossas aplicações.
Owin e Katana
A utilização de Middlewares nào é algo novo. Tecnologias como Rails (Ruby) e Express (Node) já fazem uso disso. E foi isso que o pessoal do projeto Katana fez, implementando Owin. Agora temos a estrutura de Middlewares presentes no ASP.NET 5.
O que são Middlewares?
Basicamente as novas aplicações ASP.NET não sabem fazer muita coisa. Tudo vai depender de quais Middlewares você configure e utilize em sua aplicação.
A grosso modo um Middleware é um pedaço de código que atua entre o Request e o Response para uma requisição, como a imagem abaixo ilustra:
Percebam que existe um pipeline de Middlewares, todos a serem configurados, que atuam no momento em que um Request chega, trabalhando todo ele até que o Response esteja pronto. Reparem que dependendo da ordem em que um Middleware é configurado a forma como a aplicação se comporta vai mudar, pois eles são executados na ordem que definirmos no código. Este é um ponto que abordaremos melhor em um segundo artigo.
Configurando Middlewares no ASP.NET 5
Uma coisa interessante que vamos notar em uma aplicação ASP.NET 5 é que ela pode não conter nada. Para utilizarmos o MVC adicionamos o Middleware do MVC em nossa aplicação. Vejamos um Startup.cs cru, que responde a todos os Requests com apenas uma mensagem:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Http; using Microsoft.Extensions.DependencyInjection; namespace middlewaredemo { public class Startup { public void Configure(IApplicationBuilder app) { app.Run(async (context) => { await context.Response.WriteAsync("<h1>Hello ASP.NET 5</h1>"); }); } public static void Main(string[] args) => Microsoft.AspNet.Hosting.WebApplication.Run<Startup>(args); } }
Isso é tudo que precisamos para subir uma aplicação ASP.NET. Ao rodar dnx web
podemos acessar no nosso browser:
Esta app porém não é muito inteligente, pois para todo Request ela sempre responde a mesma coisa. Vamos adicionar então o Middleware do MVC e criar uma rota, Controller e uma View 😉
Adicionando Middleware MVC
Para fazermos isso primeiro precisamos colocar a dependência do MVC em nosso project.json:
"dependencies": { "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", "Microsoft.AspNet.Mvc": "6.0.0-rc1-final" },
Feito isso vamos instalar essa dependência com dnu restore
(se você estiver no Visual Studio isso será feito automaticamente).
Agora vamos alterar o Startup.cs adicionando o serviço do MVC ao container:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); }
E ainda neste arquivo vamos dizer ao ASP.NET para usar o Middleware do MVC:
public void Configure(IApplicationBuilder app) { app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
Com isso basta criarmos um Controller e uma View para que nosso request seja tratado pelo MVC:
Com isso passamos a configurar um Request Handler (o MVC) para a nossa aplicação e no geral esse tipo de Request Handler, reutilizável, é chamado de Middleware 😀
Criando um Middleware
Podemos facilmente criar um Middleware e adicioná-lo ao nosso pipeline. Vamos usar o exemplo da própria documentação do ASP.NET e criar um Middleware que faça log dos nossos requests.
O primeiro passo para o nosso exemplo será configurar a dependência no project.json
:
"dependencies": { "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", "Microsoft.AspNet.Mvc": "6.0.0-rc1-final", "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final" }
Feito isso vamos criar uma classe que será nosso Middleware de Logging:
public static class RequestLoggerExtensions { public static IApplicationBuilder UseRequestLogger(this IApplicationBuilder builder) => builder.UseMiddleware<RequestLoggerMiddleware>(); } public class RequestLoggerMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public RequestLoggerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) { _next = next; _logger = loggerFactory.CreateLogger<RequestLoggerMiddleware>(); } public async Task Invoke(HttpContext context) { _logger.LogInformation("Handling request: " + context.Request.Path); await _next.Invoke(context); _logger.LogInformation("Finished handling request."); } }
Acima definimos uma extension para usarmos com o padrão builder no Startup.cs
e abaixo temos nosso Middleware de log. Reparem que nosso Middleware recebe um RequestDelegate chamado next que representa o próximo Middleware no nosso pipeline e recebe um objeto que implementa ILoggerFactory que será injetado no nosso Middleware pelo próprio framework.
Agora podemos apenas registrar nosso Middleware no Startup.cs
:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(minLevel: LogLevel.Information); app.UseRequestLogger(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
Primeiro adicionamos um Console Logger aos tipos de loggers disponíveis na nossa app, e então dizemos ao ASP.NET para usar nosso Middleware aqui app.UseRequestLogger();
(esta é a extension que definimos anteriormente).
Com isso ao executarmos nossa app veremos informações de log ao long de todos os requests:
O código completo do Startup.cs e do middleware de Logging está aqui neste gist: https://gist.github.com/vquaiato/f562dcfd0f3982cd92f1
Conclusão
Agora está muito simples colocar algo no pipeline do ASP.NET, utilizando o padrão de Middlewares. Tudo que precisamos fazer é criar código que receba um request e saiba trabalhá-lo, passando o request para frente, respondendo ou terminando com ele.
É possível trabalhar com Middlewares de autenticação utilizando ferramentas como o IdentityServer 3 por exemplo, ou ainda criar um Middleware de autenticação Oauth com redes sociais, as opções e possibilidades são muitas.
Abraços,
Quaiats.
Vinicius Quaiato