Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров404

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); 
// Вернет: "Ошибка: ошибка"

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

Теги:
Хабы:
-2
Комментарии0
3

Публикации

Истории

Работа

Ближайшие события