Fluent Validation em C# - A ferramenta de validação de dados poderosa e fácil de usar
A validação de dados é um dos pilares do desenvolvimento de software confiável e, em aplicações .NET modernas, você precisa de uma maneira robusta, de fácil manutenção e escalável de lidar com ela. É aí que entra o FluentValidation, uma biblioteca .NET popular para criar regras de validação fortemente tipadas.
Em seu tutorial em vídeo detalhado " Fluent Validation em C# - A Ferramenta de Validação de Dados Poderosa e Fácil de Usar ", Tim Corey guia os espectadores pelo processo de utilização do FluentValidation passo a passo. Neste artigo, seguiremos o passo a passo de Tim, resumindo os pontos principais e exemplos de código, enquanto integramos conceitos relevantes como validadores personalizados, encadeamento de validadores, integração com ASP.NET e suporte para runtimes mais antigos, como .NET Core 3.1 e .NET Standard 2.0.
Introdução: Por que usar o FluentValidation?
Tim inicia o vídeo explicando como a validação de dados muitas vezes se torna repetitiva e confusa. Por exemplo, copiar e colar regras de validação semelhantes em diferentes partes de um projeto viola o princípio DRY (Don't Repeat Yourself - Não se Repita). Em vez disso, ele apresenta o FluentValidation — uma biblioteca de validação .NET gratuita, poderosa e que funciona até mesmo em modelos que você não possui, tornando-a ideal para projetos comerciais.
Tim enfatiza a importância de praticar o que se aprende e indica aos espectadores sua série de Desafios Semanais para desenvolver habilidades.
Visão geral do aplicativo de demonstração
Tim usa um aplicativo de demonstração WinForms onde o usuário pode inserir:
-
Primeiro nome
-
Sobrenome
-
Saldo da conta
- Data de Nascimento
Embora seja uma demonstração de interface de usuário, os princípios de validação se aplicam igualmente bem ao ASP.NET Core, testes de API e até mesmo aplicativos de console.
O perigo de confiar na entrada do usuário
Nesse ponto, Tim lembra aos desenvolvedores: "Nunca confie no usuário". A entrada de dados pode ser imprevisível, como digitar "dez" em vez de "10" para idade. Validar essa entrada é essencial antes de salvar no banco de dados.
Ele descreve algumas regras de validação:
-
Os campos de nome e sobrenome não devem estar vazios.
-
O saldo da conta deve seguir as regras financeiras, como um requisito mínimo para patrocínio financeiro.
- A data de nascimento não deve ser futura nem superior a 120 anos.
Onde deve ser colocada a lógica de validação?
Tim explora opções para configurar validadores:
-
Dentro do formulário da interface do usuário
-
Na classe do modelo, usando anotações de dados
- Em uma classe de validação separada usando FluentValidation
Ele observa que as anotações de dados são limitadas e muitas vezes inadequadas ao trabalhar com bibliotecas externas ou quando é necessária uma lógica de validação mais personalizada.
Instalando o FluentValidation
Usando o Visual Studio, Tim adiciona o FluentValidation ao seu projeto via NuGet. Ele instala a versão 8.1.0, mas observa que o FluentValidation é multiplataforma e compatível com:
*.NET Standard 2.0
*.NET Core
*ASP.NET
*WPF
*Xamarin
- E mais
A configuração do Tim também funciona para quem precisa de suporte para runtimes mais antigos, incluindo o FluentValidation 11, que é compatível com o .NET Core 3.1 e versões anteriores.
Criando uma classe validadora
Tim demonstra como criar regras de validação fortemente tipadas criando uma nova classe:
public class PersonValidator : AbstractValidator<Person>
public class PersonValidator : AbstractValidator<Person>
Esta classe contém toda a lógica de validação para o modelo Pessoa. Utilizando a interface fluente, as regras de validação são definidas dentro do construtor.
Primeira regra de validação: Primeiro nome
Tim escreve uma regra usando uma expressão lambda:
RuleFor(p => p.FirstName).NotEmpty();
RuleFor(p => p.FirstName).NotEmpty();
Ele usa um validador de variáveis para validar o objeto Pessoa:
var validator = new PersonValidator();
ValidationResult results = validator.Validate(person);
var validator = new PersonValidator();
ValidationResult results = validator.Validate(person);
Em seguida, ele percorre todos os casos de falha na validação para exibir mensagens amigáveis ao usuário em uma caixa de listagem.
Comprimento da string e mensagens personalizadas
Tim amplia a regra de validação:
RuleFor(p => p.FirstName)
.NotEmpty().WithMessage("First name is empty")
.Length(2, 50).WithMessage("Length of first name is invalid");
RuleFor(p => p.FirstName)
.NotEmpty().WithMessage("First name is empty")
.Length(2, 50).WithMessage("Length of first name is invalid");
Utilizando validadores encadeados, esta regra garante que o nome não esteja vazio nem seja muito curto/longo. Tim introduz Cascade(CascadeMode.Stop) para interromper a validação na primeira falha.
Validação personalizada: caracteres válidos em nomes
Tim implementa um validador personalizado usando um método chamado:
private bool BeAValidName(string name)
private bool BeAValidName(string name)
Isso remove espaços e hífens e garante que a string contenha apenas letras Unicode, permitindo suporte para caracteres internacionais.
A regra personalizada é aplicada da seguinte forma:
.Must(BeAValidName).WithMessage("{PropertyName} contains invalid characters");
.Must(BeAValidName).WithMessage("{PropertyName} contains invalid characters");
Essa estrutura de método é perfeita para adaptação a outros campos, como uma função de lógica de validação de código postal personalizada:
private bool BeAValidPostcode(string postcode)
{
// Add custom logic here to specify a valid postcode format
}
private bool BeAValidPostcode(string postcode)
{
// Add custom logic here to specify a valid postcode format
}
Você poderia então usá-lo em um validador como:
RuleFor(c => c.Postcode).Must(BeAValidPostcode)
.WithMessage("Please specify a valid postcode");
RuleFor(c => c.Postcode).Must(BeAValidPostcode)
.WithMessage("Please specify a valid postcode");
Isso é comum em projetos comerciais que exigem a classe pública CustomerValidator ou outros validadores específicos do domínio.
Utilizando variáveis internas em mensagens de erro
Tim mostra como aprimorar mensagens dinamicamente com marcadores de posição como:
-
{NomeDaPropriedade}
-
{ComprimentoTotal}
- {ComprimentoMínimo} e {ComprimentoMáximo}
Isso resulta em mensagens de erro contextuais como:
"Length of First Name is invalid (was 105)"
"Length of First Name is invalid (was 105)"
Isso facilita a correção de erros de entrada por parte dos usuários.
Sobrenome e localização
Tim copia a lógica de validação do nome para o sobrenome, graças à formatação reutilizável com {PropertyName}. Ele também menciona o método WithLocalizedMessage() para ASP.NET ou aplicações globais que necessitam de suporte a vários idiomas.
Importante: CascadeMode é específico para cada regra.
Tim esclarece que CascadeMode.Stop se aplica a regras individuais, e não globalmente a todo o modelo. Se os campos Nome e Sobrenome estiverem vazios, ambas as regras serão acionadas, mesmo que o Modo Cascata esteja definido.
Validação da data de nascimento
Em seguida, Tim adiciona uma regra para garantir que a data de nascimento seja realista:
private bool BeAValidAge(DateTime dob)
{
var currentYear = DateTime.Now.Year;
var dobYear = dob.Year;
return dobYear <= currentYear && dobYear > (currentYear - 120);
}
private bool BeAValidAge(DateTime dob)
{
var currentYear = DateTime.Now.Year;
var dobYear = dob.Year;
return dobYear <= currentYear && dobYear > (currentYear - 120);
}
Usado assim:
RuleFor(p => p.DateOfBirth)
.Must(BeAValidAge)
.WithMessage("Invalid {PropertyName}");
RuleFor(p => p.DateOfBirth)
.Must(BeAValidAge)
.WithMessage("Invalid {PropertyName}");
Este é um bom padrão para validar dados temporais, como datas ou prazos de validade.
Considerações finais e recomendações
Tim conclui resumindo as principais vantagens do FluentValidation:
-
Lógica de validação centralizada
-
Fácil de criar validadores personalizados
-
Compatível com runtimes .NET 5 e versões mais recentes, bem como com versões mais antigas.
-
Suporta modelos complexos, listas e regras assíncronas
- Ideal tanto para amadores quanto para projetos comerciais
Ele incentiva os espectadores a explorarem a documentação do FluentValidation para usos avançados, incluindo regras aninhadas, validação de propriedades de e-mail e muito mais.
Conclusão
O FluentValidation permite que desenvolvedores .NET criem regras de validação fortemente tipadas, reutilizáveis, expressivas e de fácil manutenção. Quer você esteja desenvolvendo com .NET Core, .NET 8 ou fazendo manutenção de sistemas legados em .NET Core 3.1, esta biblioteca facilita muito a validação de dados.
Com funcionalidades como:
-
A interface fluente para a criação de regras
-
Suporte para lógica de validação de código postal personalizada
-
Fácil integração com o Visual Studio
-
Compatibilidade com testes de API, WinForms e ASP.NET
- Tratamento robusto de falhas de validação
FluentValidation é um recurso indispensável em seu conjunto de ferramentas .NET . Para mais detalhes, assista ao vídeo completo e inscreva-se no canal do Tim para mais vídeos informativos sobre C#.
Dica: Se você é iniciante no uso do FluentValidation, tente implementar seu próprio CustomerValidator com regras para propriedades como public string Name, string Postcode e outras. Faça testes com uma API simulada ou um formulário de interface de usuário para obter experiência prática.
