Fluent Validation : Customizando as mensagens


   Vamos continuar a tratar da Fluent Validation mostrando agora como customizar as mensagens.

No artigo anterior, vimos como usar os placeholders nos validators e agora veremos como personalizar as mensagens de acordo com nossas necessidades.

Sobrescrevendo a mensagem de erro

Já usamos esse método nos artigos anteriores onde passamos a mensagem de erro para este método conforme mostrado  abaixo :

RuleFor(x => x.Id).GreaterThan(0).WithMessage(“Id é inválido.”);

Este método possui outra sobrecarga que usa um delegate Func<T, string> como entrada. O que significa que qualquer método, que usa o tipo T como entrada, que está sendo validado e retorna a mensagem de erro de string, pode ser invocado via WithMessage para gerar a mensagem de erro.

...
RuleFor(x => x.Id)
    .GreaterThan(0)
    .WithMessage((estudante) =>
    {
        return $"O valor de {estudante.Id} é inválido.";
    });
...

Essa sobrecarga fornece mais flexibilidade na substituição da mensagem de erro para falha na validação.

Substituindo o nome da propriedade na mensagem

Vimos que existem duas maneiras de especificar os nomes das propriedades nas mensagens de erro – uma maneira é codificar o nome e a outra maneira é usar espaços reservados. Às vezes, os nomes das propriedades podem ser mais longos ou, em outras ocasiões, podemos usar um texto mais significativo do que apenas o nome da propriedade que está sendo validada.

Por exemplo, digamos que o modelo para o estudante tenha uma propriedade nome, mas queremos ser mais específicos e mencionar o texto “Nome completo” na mensagem de erro.

O código abaixo mostra o uso da propriedade WithName para sobrescrever a mensagem de erro:

// 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.")
  .WithName(
"Nome Completo");

Como podemos codificar diretamente a mensagem e o nome da propriedade no método WithMessage, isso pode não parecer muito útil para aplicativos simples. Mas nos aplicativos onde as mensagens de erro comuns já foram decididas com espaços reservados, este método WithName pode ser útil para definir corretamente o nome da propriedade em mensagens já definidas.

Observe que o método WithName substituirá o nome da propriedade apenas nas mensagens de erro. Após a falha da validação, você ainda encontrará o nome da propriedade real no campo “associated property” da entrada de erro na coleção Errors.

Se você quiser alterar o nome da propriedade na mensagem de erro, bem como nas propriedades associadas na coleção de erros, prefira usar o método OverridePropertyName em vez de WithName. A sintaxe para chamar esses dois métodos é a mesma.

Resolvedor de nome de exibição personalizado

Também podemos conectar a lógica personalizada para resolver os nomes. Por exemplo, se o nome da propriedade for muito grande e contiver várias palavras, podemos adicionar uma lógica personalizada para adicionar espaços entre as palavras para torná-la legível.

Suponha que o tipo Estudante tenha uma propriedade “NomeEstudante” em vez de “Nome”. E queremos exibi-lo na forma humanizada, ou seja, nome próprio. Que opções temos ?

  1. Substituir a mensagem de erro usando WithMessage e usar o nome codificado na mensagem;
  2. Usar os métodos WithName ou OverridePropertyName para substituir os nomes das propriedades nas mensagens de erro;
  3. Escrever um resolvedor de nome de membro personalizado. Esta opção deve ser selecionada apenas se houver alguma lógica comum que precise ser aplicada em vários locais.

A lógica de resolução de nome de membro pode ser personalizada atribuindo o valor Func apropriado à propriedade ValidatorOptions.Global.DisplayNameResolver

Para fins de demonstração, vamos adicionar ao projeto o pacote nuget Humanizer, que ajuda na conversão de strings em vários formatos. Queremos converter NomeCompleto que usa Pascal Case, para sua forma humanizada de caixa de título :  Nome Completo.

Para isso vamos definir no arquivo Program do projeto a seguinte configuração :

...
ValidatorOptions.Global.DisplayNameResolver = (type, member, expression) =>
{
   
// O membro nome dever ser humanizado para o respectivo titulo
   
return member?.Name.Humanize().Titleize();
};
...

Vamos alterar a propriedade da entidade Estudante de Nome para NomeCompleto e fazer isso também no controlador.

Agora, quando executamos a API, o código de inicialização configura o resolvedor personalizado. Isso significa que, se eu tentar enviar uma entrada inválida para a propriedade NomeCompleto, verei a forma humanizada do nome da propriedade, conforme mostrado abaixo :

Observe que a propriedade NomeCompleto esta sendo exibida como 'Nome Completo' na mensagem de erro conforme esperado.

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

"O que, passando, se põe em questão alheia, é como aquele que pega um cão pelas orelhas."
Provérbios 26:17

Referências:


José Carlos Macoratti