Главная страница   /   23.2. Явная валидация модели (ASP.NET MVC 4

ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

23.2. Явная валидация модели

Наиболее очевидный способ валидации модели – проверить данные в соответствующем методе действия. В листинге 23-5 показано, как мы добавили явную проверку для каждого свойства, определенного в классе Appointment, в HttpPost-версии метода действия MakeBooking.

Листинг 23-5: Осуществляем явную валидацию модели
[HttpPost]
public ViewResult MakeBooking(Appointment appt)
{
	if (string.IsNullOrEmpty(appt.ClientName))
	{
		ModelState.AddModelError("ClientName", "Please enter your name");
	}

	if (ModelState.IsValidField("Date") && DateTime.Now > appt.Date)
	{
		ModelState.AddModelError("Date", "Please enter a date in the future");
	}

	if (!appt.TermsAccepted)
	{
		ModelState.AddModelError("TermsAccepted", "You must accept the terms");
	}

	if (ModelState.IsValid)
	{
		// statements to store new Appointment in a
		// repository would go here in a real project
		return View("Completed", appt);
	}
	else
	{
		return View();
	}
}

Мы проверяем значения, которые механизм связывания присвоил свойствам объекта параметра, и регистрируем ошибки, которые находим в свойстве ModelState (его наш контроллер наследует от базового класса). Например, свойство ClientName мы проверяем таким образом:

if (string.IsNullOrEmpty(appt.ClientName)) {
	ModelState.AddModelError("ClientName", "Please enter your name");
}

Мы хотим, чтобы пользователь ввел значение для этого свойства, поэтому используем статический метод string.IsNullOrEmpty, чтобы его проверить. Если мы не получили значение, то с помощью метода ModelState.AddModelError указываем имя свойства, с которым возникла проблема (ClientName), и сообщение, которое будет показано пользователю, чтобы помочь ему исправить проблему (Please enter your name).

С помощью свойства ModelState.IsValidField мы можем проверить, смог ли механизм связывания присвоить значение. Мы применяем его в свойстве Date, чтобы убедиться, что механизм связывания смог проанализировать значение, полученное от пользователя; нет никакого смысла выполнять дополнительные проверки или регистрировать дополнительные ошибки, если значение не могло быть выделено из данных запроса.

После того как мы провели валидацию всех свойств в объекте модели, мы проверяем свойство ModelState.IsValid на наличие ошибок. Если во время проверок мы вызвали метод Model.State.AddModelError, или у механизма связывания возникли проблемы с созданием объекта Appointment, то этот метод возвращает true.

if (ModelState.IsValid)
{
	// statements to store new Appointment in a
	// repository would go here in a real project
	return View("Completed", appt);
}
else
{
	return View();
}	

Если в свойстве IsValid нет ошибок, то наш объект Appointment является действительным, и мы можем визуализировать представление Completed.cshtml (и, в реальном проекте, сохранить объект Appointment в хранилище). Если свойство IsValue возвращает false, то мы знаем, что у нас есть проблема, и вызываем метод View, который визуализирует представление по умолчанию.

Отображаем ошибки валидации пользователю

Может показаться странным, что мы обрабатываем ошибки валидации с помощью метода View, но шаблонные вспомогательные методы, которые мы использовали для создания элементов ввода в представлении MakeBooking.cshtml, проверяют модель представления на наличие ошибок валидации.

Если в свойстве появилась ошибка, вспомогательный метод добавляет к элементу ввода класс CSS под названием input-validation-error. Файл ~/Content/Site.css содержит определение по умолчанию для этого стиля, которое выглядит следующим образом:

.input-validation-error {
	border: 1px solid #f00;
	background-color: #fee;
}

Он устанавливает красную рамку и розовый фон для элемента, в котором есть ошибка. Чтобы проверить работу явной валидации, запустите приложение, перейдите по ссылке /Home/MakeBooking и нажмите кнопку Make Booking, не вводя данные в форму. Результат показан на рисунке 23-2.

Подсказка

Если вы хотите написать собственные вспомогательные методы, которые поддерживают валидацию, изучите исходный код класса System.Mvc.Web.Html.InputExtensions, чтобы понять, как это сделаеть. Вкратце скажем, что класс System.Web.Mvc.HtmlHelper определяет метод GetModelStateValue, который позволяет проверить, есть ли ошибки валидации для конкретного свойства. Есть и дополнительные методы, которые позволяют легко получить необходимый CSS и сообщения об ошибках для создания предупреждения пользователю.

Рисунок 23-2: Поля с ошибками подсвечены

Применяем стили к чекбоксам

Некоторые браузеры, в том числе Chrome и Firefox, игнорируют стили, примененные к чекбоксам, в результате чего элементы формы будут выглядеть непоследовательно. Чтобы решить эту проблему, можно заменить шаблон Boolean для элементов editor пользовательским шаблоном ~/Views/Shared/EditorTemplates/Boolean.cshtml и заключить чекбокс в элемент div. Мы используем следующий шаблон, который вы можете приспособить для своего приложения:

Этот шаблон поместит чекбокс в элемент div, к которому будет применен стиль input-validation-error, если возникнут какие-либо ошибки модели, связанные с тем свойством, к которому был применен шаблон. Вы можете узнать больше о замене шаблонов editor в главе 20.

Если вы отправите форму без данных, ошибки будут подсвечены для свойств ClientName и TermsAccepted. Значение по умолчанию для свойства Date является действительным, поэтому ошибка валидации не возникает.

Пользователь не увидит представление Completed.cshtml, пока не отправит форму с данными, которые могут быть проанализированы браузером модели (model browser), который передает операторы явной валидации в метод действия MakeBooking. В противном случае отправка формы будет визализировать представление MakeBooking.cshtml с текущими ошибками валидации.