Fluent Validation : Espaços reservados (placeholders)


   Vamos continuar a tratar da Fluent Validation mostrando como usar espaços reservados integrados em mensagens de erro personalizadas.

No artigo anterior, vimos como criar um validador e aplicar a lógica de validação às entradas nas APIs da ASP .NET Core. Vimos também como adicionar nossas próprias mensagens de erro para os validadores.

Às vezes queremos incluir nas mensagens de erros algumas coisas, como os nomes e/ou valores das propriedades ou outros valores especificados na regra de validação. Para esse propósito, a biblioteca Fluent Validation fornece vários espaços reservados integrados também chamados de placeholders.

A seguir vamos mostrar como usar espaços reservados integrados que podem ser usados nas mensagens de erro. Para fins de demonstração, vamos partir do validador que foi criado no artigo anterior, no projeto ApiFluentValidation.

Abaixo temos o código usado para criar o nosso validador EstudanteValidator :

using ApiFluentValidation.Entities;
using FluentValidation;
namespace ApiFluentValidation.Validators;
public class EstudanteValidator : AbstractValidator<Estudante>
{
    public EstudanteValidator()
    {
        // Id deve ser maior que 0
        RuleFor(x => x.Id)
            .GreaterThan(0)
            .WithMessage("Id é inválido.");
        // Nome - MinLength 10, MaxLength 100
        RuleFor(x => x.Nome)
            .MinimumLength(8)
            .WithMessage("O 'Nome' deve ter no mínimo 8 caracteres.")
            .MaximumLength(100)
            .WithMessage("O 'Nome' deve er no máximo 100 caracteres.");
        // Cursos - A coleção não pode ser nula
        // Cursos - A coleção deve ter no mínimo 5 cursos
        RuleFor(x => x.Cursos)
            .NotNull()
            .WithMessage("A coleção 'Cursos' deve ter no mínimo 5 cursos.")
            .Must((estudante, cursos, builder) => cursos.Count >= 5)
            .WithMessage("A coleção 'Cursos' deve ter no mínimo 5 cursos.");
        // Cursos - coleção - regra para cada registro
        // Cada entrada não pode ser null
        // Cada entrada deve ter no mínimo 8 e no máximo 80 caracteres
        RuleForEach(x => x.Cursos)
            .NotNull()
            .MinimumLength(8)
            .WithMessage("O nome do curso deve ter no mínimo 8 caracteres.")
            .MaximumLength(80)
            .WithMessage("O nome do curso deve ter no máximo 80 caracteres.");
    }
}

Com base no código acima vamos destacar duas mensagens de erro que usamos para a propriedade nome :

-
O 'Nome' deve ter no mínimo 8 caracteres
-
O 'Nome' deve er no máximo 100 caracteres


Como podemos ver, o nome da propriedade (ou seja, 'Nome') é codificado aqui na mensagem. E se amanhã mudarmos o nome desta propriedade para NomeEstudante ?

Teremos que ter um meio de garantir que o nome da propriedade também seja atualizado na mensagem de erro.

Outro detalhe é que temos dois números codificados, que significam o tamanho máximo permitido e o tamanho mínimo permitido. Se no futuro esses numeros forem alterados, o desenvolvedor terá que garantir que a alteração seja feita em dois lugares.

É justamente para isso que servem os placeholders ou espaços reservados: para ajudar a reduzir a duplicação e manter a consistência.

Apresentando alguns espaços reservados (placeholders)

Os dois espaços reservados, mencionados abaixo, estão disponíveis com todos os validadores.

{PropertyName}, que pode ser usado para incluir o nome da propriedade na mensagem de erro;
{PropertyValue}, que pode ser usado para incluir o valor da propriedade na mensagem de erro;

Para validadores relacionados à comparação (por exemplo, GreaterThan, LessThan, etc.), dois outros espaços reservados podem ser usados.

{ComparisonValue} – o valor com o qual a propriedade em validação está sendo comparada;
{ComparisonProperty} – o nome da propriedade que está sendo usada para manter o valor de comparação (se houver);

Em validações relacionadas ao tamanho ou comprimento, podemos usar os espaços reservados abaixo mencionados:

{MinLength} – comprimento mínimo permitido;
{MaxLength} – comprimento máximo permitido;
{TotalLength} – comprimento total da entrada;

Existe um validador, ScaleValidator, que serve para validar a precisão e a escala do número recebido. Os espaços reservados abaixo mencionados podem ser usados com este validador.

{ExpectedPrecision} – precisão esperada especificada na regra;
{ExpectedScale} – escala esperada especificada na regra;
{Digits} – número total de dígitos na entrada;
{ActualScale} – escala real da entrada;

Você pode consultar na documentação a página de validadores integrados para verificar os espaços reservados suportados por cada validador.

Como usar esses espaços reservados ?

Usar os espaços reservados é simples, em vez de codificar os nomes e valores das propriedades, podemos usar espaços reservados na mensagem. A biblioteca de validação Fluent se encarregará de substituir esses espaços reservados por seus respectivos valores.

Por exemplo, as duas mensagens de erro mencionadas para a propriedade Nome do Estudante podem ser reescritas como:

-
O '{PropertyName}' deve ter no mínimo {MinLength} caracteres
-
O
'{PropertyName}' deve er no máximo {MaxLength} caracteres

Aplicando os espaços reservados ao código do nosso validador temos o seguinte resultado:

using ApiFluentValidation.Entities;
using FluentValidation;
namespace ApiFluentValidation.Validators;
public class EstudanteValidator : AbstractValidator<Estudante>
{
    public EstudanteValidator()
    {
        // Id deve ser maior que 0
        RuleFor(x => x.Id)
            .GreaterThan(0)
            .WithMessage("O valor '{PropertyValue}' para '{PropertyName}' é inválido.");
        // Nome - MinLength 10, MaxLength 100
        RuleFor(x => x.Nome)
            .MinimumLength(8)
            .WithMessage("O '{PropertyName}' deve ter no mínimo {MinLength} caracteres.")
            .MaximumLength(100)
            .WithMessage("O '{PropertyName}' deve er no máximo {MaxLength} caracteres.");
        // Cursos - A coleção não pode ser nula
        // Cursos - A coleção deve ter no mínimo 5 cursos
        RuleFor(x => x.Cursos)
            .NotNull()
            .WithMessage("A coleção '{PropertyName}' deve ter no mínimo 5 cursos.")
            .Must((estudante, cursos, builder) => cursos.Count >= 5)
            .WithMessage("A coleção '{PropertyName}' deve ter no mínimo 5 cursos.");
        // Cursos - coleção - regra para cada registro
        // Cada entrada não pode ser null
        // Cada entrada deve ter no mínimo 8 e no máximo 80 caracteres
        RuleForEach(x => x.Cursos)
            .NotNull()
            .MinimumLength(8)
            .WithMessage("O nome do curso deve ter no mínimo 8 caracteres.")
            .MaximumLength(80)
            .WithMessage("O nome do curso deve ter no máximo 80 caracteres.");
    }
}

Para verificar vamos executar a API usando a interface do Swagger e acionando o endpoint GetEstudantes:

A resposta obtida será a seguinte :



Observe as mensagens de erros obtidas exibindo os nomes das propriedades e dos valores que foram definidos usando os placeholders.

Na próxima parte do artigo continuamos a tratar com os recursos da Fluent Validation...

"E vi um novo céu, e uma nova terra. Porque já o primeiro céu e a primeira terra passaram, e o mar já não existe."
Apocalipse 21:1

Referências:


José Carlos Macoratti