Fail-fast Validations com Pipeline Behavior no MediatR e ASP.Net Core

Esse artigo apareceu primeiro em wellingtonjhn.com

Sabemos que o MediatR simplifica muito o design de nossas aplicações tornando nosso código mais simples e com baixo acoplamento, conforme eu mostrei no artigo anterior. Se você não viu corre lá e depois volte aqui.

Um dos recursos mais legais dele é a possibilidade de executarmos determinadas ações antes ou depois de um Handler ser disparado. Esse recurso leva o nome de Pipeline Behavior.

Você pode usar o Pipeline Behavior para, por exemplo, validar os parâmetros de entrada dos Requests, autorizar o acesso à determinado Handler, gravar log dos Requests, etc.

Lembre-se do artigo anterior, quando eu me refiro à Request no MediatR não estou falando de uma requisição HTTP, mas sim da “mensagem” que é enviada para o MediatR, e que está associada a determinado Handler.

Como funciona?

O Pipeline Behavior é bem parecido com o pipeline de execução do ASP.Net Core, onde temos middlewares sendo executados sequencialmente.

Para usar esse recurso do MediatR você deve criar uma classe que implementa a interface IPipelineBehavior<TRequest, TResponse>. Nessa classe iremos definir o comportamento que desejamos.

Exemplo de Pipeline Behavior que apenas faz um log das chamadas do MediatR

Veja que um dos parâmetros do Pipeline Behavior é um Request. Além disso, ele usa o método next() para disparar o próximo passo do pipeline, que normalmente é a execução do respectivo Handler.

Após implementar a classe você deve registrá-la no container de DI de sua preferência. No meu caso irei usar o container nativo do ASP.Net Core mais adiante.

Quando um Request for enviado para o MediatR, os Behaviors serão executados na sequência em que foram definidos no container de DI.


Fail-Fast Validations

Em nosso exemplo iremos implementar um Behavior para validar os parâmetros de entrada dos Requests antes de seus respectivos Handlers serem disparados, dessa forma antecipamos a falha no Request e poupamos nossa aplicação de processar um Handler para descobrir que os parâmetros não são válidos.

Normalmente a validação dos Requests é feita na entrada do Handler ou nas Actions dentro das Controllers da API, com chamadas para validar os inputs de dados. Isso torna o código um pouco sujo na minha opinião. A implementação do Behavior torna essa tarefa automática.

Para implementar esse Behavior usaremos o MediatR em conjunto com a biblioteca FluentValidation que acredito ser uma das mais conhecidas e utilizadas mundialmente quando falamos de validações. Caso você queira usar outra biblioteca de Notification Pattern nas validações fique à vontade, as alterações seriam mínimas. Recomendo você dar uma olhada no Flunt.


Implementação

A classe a seguir representa nosso Behavior responsável por interceptar todos os Requests.

Veja que injetamos em nosso Behavior todos os validadores do FluentValidation. No método Handle executamos os validadores e caso existam falhas apontadas por eles, interrompemos o pipeline e então retornamos essas mensagens de erro.

Pipeline Behavior para fazer Fail-Fast

A seguir temos um Request e seu respectivo Validator que irá garantir que os parâmetros do Request estejam em conformidade.

Request com seu respectivo Validator

Na classe Startup de nossa API temos o método AddMediatr, que é responsável por fazer a devida injeção de dependências do MediatR além dos validadores de Requests.

Injeção de Dependência do MediatR com os Validators do Fluent Validator

Na controller apenas enviamos o Request para o MediatR e então recuperamos seu retorno. Caso ele retorne mensagens de erro, elas são exibidas com o Http Status Code 400 (Bad Request).

Controller limpa chamando o MediatR

Podemos fazer os testes de execução da API com o Postman.

Chamada com todas as mensagens de validação do Request
Mensagem de e-mail inválido
Chamada de Sucesso na API

Conclusão

Você deve ter percebido que as mensagens são cumulativas, então podemos validar todos os parâmetros e retornar as falhas de uma única vez.

Muitas APIs por aí fazem a validação campo à campo, disparando uma Exception para cada propriedade inválida. Essa abordagem é muito ruim na minha opinião, pois além de interromper o fluxo para cada propriedade inválida ainda existe o lançamento de Exception que é muito oneroso para a aplicação.

Usando uma abordagem de Fail-fast com Notification Pattern, nosso código fica mais limpo e as validações dos Requests, caso existam, serão executadas automaticamente dentro do pipeline do MediatR antes que seus respectivos Handlers sejam disparados.

Quaisquer dúvidas ou sugestões, por favor entrem em contato.

Abraços!!

Não deixe de conferir o código fonte para essa demo que está no meu Github.


Tableless

Um lugar para ler e discutir sobre desenvolvimento, design, web semântica, back-end e outros assuntos relacionados a web. Se você quiser publicar artigos conosco, envie um email: medium[at]tableless.com.br ou *clique no link* http://bit.ly/escreva-tableless-medium

Wellington Nascimento

Written by

https://www.wellingtonjhn.com

Tableless

Tableless

Um lugar para ler e discutir sobre desenvolvimento, design, web semântica, back-end e outros assuntos relacionados a web. Se você quiser publicar artigos conosco, envie um email: medium[at]tableless.com.br ou *clique no link* http://bit.ly/escreva-tableless-medium

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade