Проверка формы веб-приложения - дизайн для распространения ошибок домена на стороне клиента?
Проверка данных должна выполняться в следующих местах в веб-приложении:
- Клиентская сторона: браузер. Чтобы ускорить отчет об ошибках пользователя
- Серверная сторона: контроллер. Чтобы проверить, является ли вход пользователя синтаксически действительным (без инъекций sql, например, допустимого формата для всех переданных в полях, все обязательные поля заполняются и т.д.).
- Серверная сторона: модель (доменный уровень). Чтобы проверить, действительно ли вход пользователя действителен (не дублирует имена пользователей, баланс аккаунта не является отрицательным и т.д.).
В настоящее время я являюсь поклонником DDD, поэтому у меня есть слои пользовательского интерфейса и домена, разделенные в моих приложениях.
Я также пытаюсь следовать правилу, эта модель домена никогда не должна содержать недопустимые данные.
Итак, как вы создаете механизм проверки в своем приложении, чтобы ошибки проверки, происходящие в домене, правильно распространялись на клиента? Например, когда модель домена вызывает исключение о дублированном имени пользователя, как правильно привязать это исключение к представленной форме?
Некоторые статьи, которые вдохновили этот вопрос, можно найти здесь: http://verraes.net/2015/02/form-command-model-validation/
Я не видел таких механизмов в известных веб-фреймворках. Первое, что приходит в голову, состоит в том, чтобы сделать модель домена включением имени поля, вызывающего исключение, в данных исключения, а затем на уровне пользовательского интерфейса предоставить карту между полями данных формы и полями данных модели, чтобы правильно отобразить ошибку в этом контексте для пользователя. Является ли этот подход действительным? Это выглядит шатким... Есть ли примеры лучшего дизайна?
Ответы
Ответ 1
Хотя не тот же вопрос, что и этот, я думаю, что ответ тот же:
Инкапсулировать логику проверки в класс многократного использования. Эти классы обычно называются спецификациями, валидаторами или правилами и являются частью домена.
Теперь вы можете использовать эти спецификации как в модели, так и в уровне обслуживания.
Если ваш пользовательский интерфейс использует ту же технологию, что и модель, вы также можете использовать там спецификации (например, при использовании NodeJS на сервере вы можете писать спецификации в JS и использовать их в браузере, слишком).
Изменить - дополнительная информация после чата
- Создавайте мелкозернистые спецификации, чтобы вы могли отображать соответствующие сообщения об ошибках, если сбой спецификации.
- Не вводите бизнес-правила или спецификации в поля формы.
- Создавайте спецификации для бизнес-правил, а не для основных задач проверки ввода (например, для проверки на нуль).
Ответ 2
Я хочу использовать подход, используемый нами в одном проекте DDD.
- Мы создали BaseClass с полями ErrorId &
ErrorMessage.
-
Каждый DomainModel получается из этого BaseClass и, следовательно, имеет два дополнительных поля ErrorId и ErrorMessage, доступные из
BaseClass.
-
Всякий раз, когда возникает исключение, мы обрабатываем исключение (регистрируемся на сервере, предпринимаем соответствующие шаги для компенсации логики и извлекаем сообщение "Удобное для пользователя" из локализованного файла ресурсов локализации клиента для сообщения), а затем распространять данные как простой поток без исключения исключения или исключения.
-
На стороне клиента проверьте, не является ли ErrorMessage недействительным, затем покажите ошибку.
Это простой простой подход, который мы выполнили с момента запуска проекта.
Если это новый проект, это наименее сложный и эффективный подход, но если вы вносите изменения в большой старый проект, это может не помочь, поскольку изменения большие.
Для проверки на каждом уровне поля используйте Блок приложений проверки из Корпоративной библиотеки.
Его можно использовать как:
Украсить свойства модели домена соответствующими атрибутами:
public class AttributeCustomer
{
[NotNullValidator(MessageTemplate = "Customer must have valid no")]
[StringLengthValidator(5, RangeBoundaryType.Inclusive,
5, RangeBoundaryType.Inclusive,
MessageTemplate = "Customer no must have {3} characters.")]
[RegexValidator("[A-Z]{2}[0-9]{3}",
MessageTemplate = "Customer no must be 2 capital letters and 3 numbers.")]
public string CustomerNo { get; set; }
}
Создайте экземпляр проверки, например:
Validator<AttributeCustomer> cusValidator =
valFactory.CreateValidator<AttributeCustomer>();
Использовать объект и выполнить проверку как:
customer.CustomerNo = "AB123";
customer.FirstName = "Brown";
customer.LastName = "Green";
customer.BirthDate = "1980-01-01";
customer.CustomerType = "VIP";
ValidationResults valResults = cusValidator.Validate(customer);
Проверьте результаты проверки как:
if (valResults.IsValid)
{
MessageBox.Show("Customer information is valid");
}
else
{
foreach (ValidationResult item in valResults)
{
// Put your validation detection logic
}
}
Пример кода берется из Microsoft Enterprise Library 5.0 - Введение в блок проверки
Эти ссылки помогут понять блок Application Validation:
http://www.codeproject.com/Articles/256355/Microsoft-Enterprise-Library-Introduction-to-V
https://msdn.microsoft.com/en-in/library/ff650131.aspx
https://msdn.microsoft.com/library/cc467894.aspx