Quem trabalha com back-end de aplicações web, sabe a necessidade de ter o controle do fluxo da sua aplicação. Filtros, autorização, tokens e desserialização são algumas das necessidades mais comuns no mundo back-end.
Quando trabalhamos com .NET Core, esse controle é extremamente simplificado, pois ele foi arquitetado para ter ganchos e cada parte de uma requisição. Isso significa que podemos injetar código em diversas partes da pipeline da requisição, sem a necessidade workarounds (gambs, para os íntimos).
Isso abre diversas oportunidades para escrevermos código de boa qualidade, e com uma única responsabilidade. Para exemplificar o uso dos ganchos oferecidos, criei uma aplicação WebApi simples, com os seguintes filtros implementados: Resource Filter, Action Filter, Exception Filter e Result Filter; alguns exemplos para abrir o caminho, e o restante fica por sua necessidade em suas aplicações.
Filtros de Recurso
Tem a função de checar algum recurso de requisição, como cache ou valores de formulários antes do binding. Implementa a interface IResourceFilter:
public class ResourceFilter : IResourceFilter { public void OnResourceExecuting(ResourceExecutingContext context) { Console.WriteLine("Passando pelo Resource Filter ANTES do metodo"); } public void OnResourceExecuted(ResourceExecutedContext context) { Console.WriteLine("Passando pelo Resource Filter DEPOIS do metodo"); } }
Ainda no Resource Filter, temos acesso ao ModelState, Session, ao objeto RouteData (onde podemos, inclusive, alterar o valor de um parâmetro de rota) e muitas outras propriedades.
Action Filter
Esse filtro é chamado logo antes e logo depois da ACTION, por isso, já temos acesso a uma instância do controller, e do ModelState também. Implementa a interface IActionFilter:
public class ActionFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { Console.WriteLine("Passando pelo Action Filter ANTES do metodo"); } public void OnActionExecuted(ActionExecutedContext context) { Console.WriteLine("Passando pelo Action Filter DEPOIS do metodo"); } }
Exception Filter
Uma classe especial de filtros, chamada somente em caso da action lançar uma exceção não tratada, muito utilizada para logging e tratamento da mensagem para uma forma amigável. Implementa a interface IExceptionFilter:
public class ExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { Console.WriteLine("Uma exceção não tratada ocorreu na action"); } }
Nesse filtro, temos acesso ao ModelState também, e também temos como acessar a exceção que foi lançada.
Result Filter
Já nesse último filtro, é o passo antes de retornar a resposta para o usuário. Aqui, já temos o retorno da Action, e podemos adicionar headers, logging de sucesso e do resultado gerado, entre outras informações. Implementa a interface IResultFilter, com dois métodos: OnResultExecuting e OnResultExecuted. No primeiro é onde podemos alterar a resposta, é a nossa última chance de alterar algo antes de retornar para o usuário. No segundo método, a resposta já foi retornada, e não há mais como alterar nada.
public class ResultFilter : IResultFilter { public void OnResultExecuting(ResultExecutingContext context) { Console.WriteLine("Passando pelo result filter antes de retornar ao usuario."); } public void OnResultExecuted(ResultExecutedContext context) { Console.WriteLine("Passando pelo result filter apos retornar ao usuario, ja nao podemos alterar a resposta."); } }
Para adicionar esses filtros que criamos no pipeline das requisições (de forma global, para exemplificar), adicionamos esses filtros ao declarar o uso do MVC na classe Startup:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.Filters.Add(new ResourceFilter()); options.Filters.Add(new ActionFilter()); options.Filters.Add(new ExceptionFilter()); options.Filters.Add(new ResultFilter()); }); }
Rodando nossa aplicação, chamando o controller Teste (está no código fonte citado no início do artigo), temos o seguinte resultado no console:
É importante lembrar que podemos criar mais de um filtro do mesmo tipo e adicionar ao pipeline, é uma ferramenta de extrema importância para o desacoplamento de código e que poucos usam com seu total potencial. Neste exemplo simples, usamos somente o console para exemplificar, mas as possibilidades são inúmeras.
Não pare com os estudos, e busque implementar essa funcionalidade em seus projetos no trabalho ou estudo para fixar o conhecimento.
Um forte abraço, e até a próxima!