O FluentValidation é uma biblioteca que é utilizada para validar objetos de formas simples, expressivas e desacoplada da lógica da aplicação.
É necessário utilizar o FluentValidation quando:
- Você quer separação de responsabilidades (validar fora da model).
- Regras complexas ou condicionais são frequentes.
- Precisa de reutilização e testes unitários em validações.
Dependendo do tamanho do projeto, fazer as validações de objetos em C# pode ser estressante e cansativo. Sempre que criamos uma aplicação, temos modelos que podem ser validados. Essas validações além de complexas podem se tornar incompreensíveis se forem mal escrita, o Fluent Validation é uma ferramenta disponível no mercado que simplifica a forma como fazemos nossas validações. Com ele podemos validar nossas propriedades e objetos de forma clara e de fácil compreensão, além de fáceis de se testar.
Existem várias vantagens em utilizar essa biblioteca, seus destaques são:
- Separacão das Preocupações: A validação é separada da regra de negócio e da camada de dados.
- Sintaxe Fluente: Sintaxe intuitiva e legível, permitindo que você escreva validações de forma clara e concisa.
- Extensibilidade: Você pode estender a biblioteca para adicionar suas próprias regras de validação ou modificar o comportamento existente.
- Mensagens de erros personalizadas
- Integração com o ASP NET Core
Instalando pacote no Nuget
Para começar, é necessário instalar o pacote:
- Se quiser utilizar integrado com o ASP NET Core
Install-Package FluentValidation.AspNetCore
- Se quiser utilizar manualmente
Install-Package FluentValidation
Abordagens
Existem várias formas de abordar esse tipo de validação. A escolha depende da necessidade do projeto. Existem várias formas, mas as mais conhecidas são
- Abordagem Manual
- Integração com ASP.NET Core
Integração com o ASP NET Core
Quando se utiliza a abordagem de integração, ganha uma série de vantagens
1. Validação automática de modelo
Validação automática do modelo. O ASP.NET chama o validator automaticamente antes do controller ser executado e caso haja erros, já retorna 400 Bad Request
{
"errors": {
"Email": ["O campo é obrigatório."],
"Idade": ["Deve ter no mínimo 18 anos."]
}
}
2. Menos código repetido
Você não precisa instanciar e validar manualmente o objeto em cada endpoint. Evitando códigos como esse abaixo:
var validator = new UsuarioValidator();
var resultado = validator.Validate(usuario);
3. Integra com o ModelState do ASP.NET
Todos os erros vão para ModelState
, e você pode usar normalmente, mas nem precisa — o ASP.NET já faz isso pra você com [ApiController]
.
if (!ModelState.IsValid) return BadRequest(ModelState);
4. Resposta de erro padronizada e automatizada
Já vem com formatação automática (e pode ser personalizada), o que é uma boa prática para APIs RESTful.
5. Reaproveitamento de regras
Pode usar a mesma validação na API e em serviços internos. Por exemplo: mesma PessoaValidator
no Controller
, Service
, ou BackgroundJob
.
6. Testabilidade e separação de responsabilidade
Facilita testes unitários das validações de forma isolada.
var validator = new UsuarioValidator();
var resultado = validator.Validate(usuario);
Assert.False(resultado.IsValid);
Exemplo Prático
Estrutura do projeto
Projeto
├── Controllers
│ └── UsuarioController.cs
├── Models
│ └── Usuario.cs
├── Validators
│ └── UsuarioValidator.cs
└── Program.cs
1. Modelo
Primeiro, vamos definir um modelo simples chamado Cliente
.
public class Cliente
{
public string Nome { get; set; }
public string Email { get; set; }
public int Idade { get; set; }
}
2. Validador
O segundo arquivo será o nosso próprio validador.
Ele estende a classe AbstractValidator<T>
, onde T
é o tipo que você deseja validar.
Ao herdar o AbstractValidator<T>,
o NovoClienteValidator
herda todas as funcionalidades da classe base, permitindo definir regras de validação específicas para o modelo Cliente
using FluentValidation;
public class NovoClienteValidator : AbstractValidator<Cliente>
{
public NovoClienteValidator()
{
RuleFor(cliente => cliente.Nome)
.NotEmpty().WithMessage("O nome é obrigatório.")
.Length(2, 50).WithMessage("O nome deve ter entre 2 e 50 caracteres.");
RuleFor(cliente => cliente.Email)
.NotEmpty().WithMessage("O email é obrigatório.")
.EmailAddress().WithMessage("O email fornecido não é válido.");
RuleFor(cliente => cliente.Idade)
.InclusiveBetween(18, 100).WithMessage("A idade deve estar entre 18 e 100 anos.");
}
}
3. Controller
Agora, vamos criar um controlador que usa o modelo Cliente
e valida as solicitações de entrada.
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ClientesController : ControllerBase
{
[HttpPost]
public IActionResult CriarCliente([FromBody] Cliente cliente)
{
// A validação será feita automaticamente pelo FluentValidation
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Lógica para adicionar o cliente no banco de dados (omita por simplicidade)
return Ok("Cliente criado com sucesso!");
}
}
4. Configuração de Startup
Existem duas abordagem para configurar o Fluent API.
A. Configuração simples feita diretamente no arquivo de inicialização (Startup), que funciona bem para projetos menores.
B. Abordagem mais robusta e é usada em projetos maiores e mais complexos, oferecendo mais flexibilidade.
A. No Arquivo Startup
using AL.Manager.Validator.Conta;
using AL.WebApi.Configuration;
using CL.WebApi.Configuration;
using FluentValidation.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddValidatorsFromAssemblyContaining<Program>(); // Vai registrar todos os validadores do seu projeto
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDataBaseConfiguration(builder.Configuration);
builder.Services.AddDependencyInjectionConfiguration();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseDatabaseConfiguration();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
B. Arquivo de Configuração
A segunda abordagem é criar em um arquivo de configuração. Na mesma raiz do projeto: Configuration/FluentValidationConfig
using AL.Manager.Validator.Conta;
using FluentValidation.AspNetCore;
using System.Globalization;
namespace CL.WebApi.Configuration;
public static class FluentValidationConfig
{
public static void AddFluentValidationConfiguration(this IServiceCollection services)
{
services.AddValidatorsFromAssemblyContaining<Program>(); // Vai registrar todos os validadores do seu projeto
}
}
Agora é necessário chamar o nosso método criado anteriormente no startup
do programa.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddFluentValidationConfiguration();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDataBaseConfiguration(builder.Configuration);
builder.Services.AddDependencyInjectionConfiguration();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseDatabaseConfiguration();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.