Skip to content

Projeto de exemplo que demonstra a implementação de validações robustas e fluentes em aplicações .NET usando a biblioteca FluentValidation. Utiliza uma API de pagamentos como caso de uso prático para ilustrar a criação de validadores, regras customizadas e integração com ASP.NET Core.

License

Notifications You must be signed in to change notification settings

emensonlima01/fluent-validation-dotnet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 

Repository files navigation

FluentValidation com .NET

Descrição

Projeto de exemplo que demonstra a implementação de validações robustas e fluentes em aplicações .NET usando a biblioteca FluentValidation. Utiliza uma API de pagamentos como caso de uso prático para ilustrar a criação de validadores, regras customizadas e integração com ASP.NET Core.

O que este projeto demonstra

  • Integração do FluentValidation com ASP.NET Core 8.0
  • Criação de classes de validação para DTOs (Data Transfer Objects)
  • Uso de regras de validação encadeadas e fluentes
  • Implementação de validadores customizados para regras de negócio específicas (CPF/CNPJ)
  • Validação de campos seguindo regras de negócio brasileiras
  • Injeção de dependência para validadores
  • Deploy containerizado com Docker

Como o FluentValidation é Utilizado

Estrutura de Validadores

O projeto organiza os validadores no projeto Application, seguindo a estrutura do domínio:

Application/
└── Validators/
    └── Payment/
        ├── BankAccountRequestValidator.cs
        └── GeneratePaymentRequestValidator.cs

Cada DTO possui sua própria classe de validação, que herda de AbstractValidator<T>.

Regras de Validação

As regras são definidas de forma declarativa e legível no construtor de cada validador. O projeto inclui exemplos de:

  • Regras básicas: NotEmpty(), Length(), GreaterThan().
  • Regras de formato: Matches("^[0-9]*$") para garantir que um campo contenha apenas dígitos.
  • Validadores aninhados: Um validador pode reutilizar outro para validar propriedades complexas (SetValidator(new BankAccountRequestValidator())).
  • Validadores de enumeração: IsInEnum() para garantir que o valor corresponda a um membro de um Enum.
  • Validadores customizados: O projeto inclui um validador customizado para CPF/CNPJ, demonstrando a extensibilidade da biblioteca.

Integração com ASP.NET Core

A integração é feita de forma transparente no Program.cs:

  1. Os validadores são registrados no contêiner de injeção de dependência com AddValidatorsFromAssemblyContaining<T>().
  2. O middleware do FluentValidation é habilitado com AddFluentValidationAutoValidation().

Com isso, o ASP.NET Core automaticamente intercepta as requisições, localiza o validador apropriado para o DTO e executa a validação antes de o controller ser acionado. Em caso de falha, retorna uma resposta 400 Bad Request com os detalhes dos erros.

Tecnologias

  • FluentValidation - Biblioteca para validação de objetos
  • Extensions.FluentValidation.Br - Extensões para validação de CPF/CNPJ
  • ASP.NET Core 8.0 - Framework para a API de exemplo
  • Docker - Containerização da aplicação
  • Clean Architecture - Separação de responsabilidades

Configuração

Pré-requisitos

  • .NET 8 SDK
  • Docker e Docker Compose (opcional, para execução em container)

Executar o Projeto

Via .NET CLI

# Navegue até a pasta da solução
cd Solution

# Execute a WebApi
cd WebApi
dotnet run

A API estará disponível em http://localhost:5192 (ou outra porta, verifique o output do console).

Via Docker

docker-compose up -d

Isso irá iniciar a API na porta 5192.

Testar a API de Exemplo

Acesse http://localhost:5192/swagger para explorar os endpoints. Tente enviar uma requisição para POST /api/payment com dados inválidos para ver o FluentValidation em ação.

Exemplo de corpo de requisição inválido:

{
  "originAccount": {
    "accountNumber": "123",
    "accountHolder": "",
    "bankCode": "1234",
    "branchCode": "123",
    "documentNumber": "111.111.111-11"
  },
  "destinationAccount": {
    "accountNumber": "12345",
    "accountHolder": "Jane Doe",
    "bankCode": "001",
    "branchCode": "1234",
    "documentNumber": "12.345.678/0001-99"
  },
  "amount": 0,
  "methodId": 99
}

Resposta esperada (400 Bad Request):

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "OriginAccount.AccountNumber": [
      "Account number must be between 5 and 12 digits."
    ],
    "OriginAccount.AccountHolder": [
      "Account holder is required."
    ],
    "OriginAccount.BankCode": [
      "Bank code must be 3 digits."
    ],
    "OriginAccount.BranchCode": [
      "Branch code must be 4 digits."
    ],
    "Amount": [
      "Amount must be greater than zero."
    ],
    "MethodId": [
      "Invalid payment method."
    ]
  }
}

Implementação do FluentValidation

Validador de Conta Bancária

// Application/Validators/Payment/BankAccountRequestValidator.cs
public class BankAccountRequestValidator : AbstractValidator<BankAccountRequest>
{
    public BankAccountRequestValidator()
    {
        RuleFor(x => x.AccountNumber)
            .NotEmpty()
            .Length(5, 12)
            .Matches("^[0-9]*$")
            .WithMessage("Account number must be between 5 and 12 digits.");

        RuleFor(x => x.BankCode)
            .NotEmpty()
            .Length(3)
            .Matches("^[0-9]*$")
            .WithMessage("Bank code must be 3 digits.");

        RuleFor(x => x.DocumentNumber)
            .NotEmpty()
            .IsValidCpfOrCnpj()
            .WithMessage("Document number must be a valid CPF or CNPJ.");
    }
}

Validador Customizado (CPF/CNPJ)

// Application/Validators/Custom/CustomValidators.cs
public static class CustomValidators
{
    public static IRuleBuilderOptions<T, string> IsValidCpfOrCnpj<T>(this IRuleBuilder<T, string> ruleBuilder)
    {
        return ruleBuilder.Must(document =>
        {
            if (string.IsNullOrEmpty(document)) return false;
            var doc = new string(document.Where(char.IsDigit).ToArray());
            if (doc.Length == 11) return IsCpf(doc);
            if (doc.Length == 14) return IsCnpj(doc);
            return false;
        }).WithMessage("Invalid CPF or CNPJ.");
    }

    // ... métodos privados IsCpf e IsCnpj
}

Injeção de Dependência

// WebApi/Extensions/Payment/PaymentDependencyInjection.cs
public static IServiceCollection AddPaymentServices(this IServiceCollection services)
{
    // ... outros serviços
    services.AddValidatorsFromAssemblyContaining<GeneratePaymentRequestValidator>();
    return services;
}

// WebApi/Program.cs
builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddPaymentServices();

Arquitetura do Projeto

O projeto segue Clean Architecture com separação clara de responsabilidades:

Solution/
├── Domain/              # Regras de negócio e entidades
├── Application/        # Casos de uso e validação
│   ├── UseCases/      # Lógica de aplicação
│   ├── DTOs/          # Objetos de transferência
│   └── Validators/    # Classes de validação
├── Infrastructure/     # Implementações técnicas
├── WebApi/            # API REST
└── Shared/            # Utilitários compartilhados

Benefícios desta arquitetura:

  • Validadores desacoplados dos controllers e da lógica de negócio.
  • Testabilidade facilitada.
  • Reutilização de validadores.

Referências

FluentValidation

.NET

Arquitetura

About

Projeto de exemplo que demonstra a implementação de validações robustas e fluentes em aplicações .NET usando a biblioteca FluentValidation. Utiliza uma API de pagamentos como caso de uso prático para ilustrar a criação de validadores, regras customizadas e integração com ASP.NET Core.

Topics

Resources

License

Stars

Watchers

Forks