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)); }
Как вы видите, локальная или глобальная переменная – значения не имеет.
Резюмируем про переменные:
-
Ошибку вам не подсветит, но когда будете выполнять, сломается, потому что пустое сообщение.
var str = ""; ... .Must(x => str += "Ошибка"; return false; ) .WithMessage(str); // Ничего не вернет, ошибка
-
Даже если что-то добавите, метод возьмет то, что было изначально.
var str = ""; ... .WithMessage($"Ошибка: {str}"); // Вернет: "Ошибка: "
var str = "Ошибка: "; ... .Must(x => str += "ошибка"; return false; ) .WithMessage(str); // Вернет: "Ошибка: "
Это относится не только к строковым переменным, а любым, что бы вы там не выводили.
-
А вот так будет работать корректно. Используем лямбда-выражения, если объект вам не нужен в формировании сообщения, можно поставить _
var str = "Ошибка: "; ... .Must(x => str += "ошибка"; return false; ) .WithMessage(_ => str); // Вернет: "Ошибка: ошибка"
На этом у меня все. Поправьте меня, если что-то не так. Но это то, с чем я боролась последние несколько дней.
ссылка на оригинал статьи https://habr.com/ru/articles/873068/
Добавить комментарий