Кастомные сообщения об ошибках в FluentValidation

от автора

FluentValidation — это мощная библиотека для валидации объектов в .NET, которая поддерживает создание кастомных сообщений об ошибках. В этом руководстве мы рассмотрим, как использовать различные подходы к формированию этих сообщений и почему важно различать использование простых строк и лямбда-выражений в методе WithMessage.

Простой вывод сообщения об ошибке

Когда вы используете метод WithMessage и передаете строку напрямую:

RuleFor(customer => customer.FirstName)     .NotNull()     .WithMessage("Это сообщение об ошибке."); 

В данном случае сообщение выводится как есть, но оно не позволяет динамически управлять содержимым. Если вам необходимо добавить динамически изменяемые или кастомные сообщения, стоит рассмотреть использование лямбда-выражений.

Динамическое формирование сообщения с помощью лямбда-выражения

Используя перегрузку метода WithMessage, вы можете передать лямбда-выражение, которое будет возвращать строку:

RuleFor(customer => customer.FirstName)     .NotNull()     .WithMessage(customer => $"Ошибка: {customer.FirstName} не может быть пустой."); 

Этот способ позволяет вам динамически использовать значения, которые могут меняться в зависимости от состояния объекта в процессе валидации. Также вы можете использовать ссылки на другие свойства проверяемого объекта.

Использование пользовательских аргументов

Согласно документации FluentValidation (очень не очевидно там, конечно, это написано), вы можете использовать собственные аргументы в сообщении о проверке. Это могут быть как статические значения, так и ссылки на другие свойства проверяемого объекта.

Пример из документации:

RuleFor(customer => customer.Фамилия)     .NotNull()     .WithMessage(customer => string.Format("Это сообщение ссылается на некоторые константные значения: {0} {1}", "привет", 5)); // Результат будет таким: "Это сообщение ссылается на некоторые константные значения: привет 5"

Но это так же будет работать, если вы будете собирать сообщение об ошибке в Must или MustAsync

private List<string> ValidationErrors = new List<string>();  public ExampleValidator() {     RuleFor(x => x)         .MustAsync(async (x, cancellation) =>         {             ValidationErrors.Add("Ошибка1");             return false;         })         .WithMessage(x => string.Join(", ", ValidationErrors)); }
public ExampleValidator() {     var validationErrors = new List<string>();     RuleFor(x => x)         .Must((x, cancellation) =>         {             ValidationErrors.Add("Ошибка1");             return false;         })         .WithMessage(x => string.Join(", ", validationErrors)); }

Как вы видите, локальная или глобальная переменная – значения не имеет.

Резюмируем про переменные:

  1. Ошибку вам не подсветит, но когда будете выполнять, сломается, потому что пустое сообщение.

var str = ""; ... .Must(x =>      str += "Ошибка";      return false;    ) .WithMessage(str);  // Ничего не вернет, ошибка
  1. Даже если что-то добавите, метод возьмет то, что было изначально.

var str = ""; ... .WithMessage($"Ошибка: {str}");  // Вернет: "Ошибка: "
var str = "Ошибка: "; ... .Must(x =>        str += "ошибка";        return false;      ) .WithMessage(str);  // Вернет: "Ошибка: "

Это относится не только к строковым переменным, а любым, что бы вы там не выводили.

  1. А вот так будет работать корректно. Используем лямбда-выражения, если объект вам не нужен в формировании сообщения, можно поставить _

var str = "Ошибка: "; ... .Must(x =>        str += "ошибка";        return false;      ) .WithMessage(_ => str);  // Вернет: "Ошибка: ошибка"

На этом у меня все. Поправьте меня, если что-то не так. Но это то, с чем я боролась последние несколько дней.


ссылка на оригинал статьи https://habr.com/ru/articles/873068/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *