ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

Отображение сообщений валидации

CSS стили, которые применяются шаблонными вспомогательными методами к элементам ввода, указывают на проблему с полем, но не сообщают пользователю, в чем эта проблема заключается. К счастью, для этого существуют другие вспомогательные методы. В листинге 23-6 показан один из таких методов, который мы применили к представлению MakeBooking (так как именно оно демонстрирует ошибки валидации пользователю).

Листинг 23-6: Используем вспомогательный метод ValidationSummary
<h4>Book an Appointment</h4>

@using (Html.BeginForm())
{
	@Html.ValidationSummary()
	<p>Your name: @Html.EditorFor(m => m.ClientName)</p>
	<p>Appointment Date: @Html.EditorFor(m => m.Date)</p>
	<p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms & conditions</p>
	<input type="submit" value="Make Booking" />
}

Вспомогательный метод Html.ValidationSummary добавляет сообщение об ошибках валидации, которые были зарегистрированы на отображаемой пользователю странице. Если ошибок нет, то вспомогательный метод не генерирует HTML. На рисунке 23-3 показан результат применения этого метода. Мы очистили поля ввода и отправили форму.

Рисунок 23-3: Отображение сообщения валидации

Примечание

Для свойства Date мы используем значения в американском формате даты month/day/year. Если вы находитесь в другой стране, то можете ввести допустимые даты в местном формате (например, day/month/year, который широко используется в Европе) или добавить для этого проекта строку <globalization culture="en-US" uiCulture="en-US"/> в элемент system.web в файле Web.config, чтобы приложение использовало формат даты US.

В сообщении валидации отображается информация об ошибках, которые были зарегистрированы в ModelState в методе действия MakeBooking. Этот вспомогательный метод генерирует следующий HTML:

<div class="validation-summary-errors" data-valmsg-summary="true">
	<ul>
		<li>Please enter your name</li>
		<li>Please enter a date in the future</li>
		<li>You must accept the terms</li>
	</ul>
</div>

Ошибки выводятся в виде списка в элементе div, к которому применен стиль validation-summary-errors. Этот стиль определен в ~/Content/Site.css и по мере необходимости может быть изменен. По умолчанию стиль выделяет текст сообщений об ошибках полужирным и красным:

.validation-summary-errors {
	font-weight: bold;
	color: #f00;
}

Для метода ValidationSummary существует несколько перегруженных версий; наиболее полезные из них показаны в таблице 23-1. Некоторые из этих версий позволяют указать, что нужно отображать только ошибки уровня модели (model-level errors). Ошибки, которые до сих пор были зарегистрированы в ModelState, относятся к уровню свойства (property-level errors) и означают, что для данного свойства указано недействительное значение; если его изменить, проблема будет решена.

Таблица 23-1: Полезные перегруженные версии вспомогательного метода ValidationSummary
Перегруженный метод Описание
Html.ValidationSummary() Генерирует сообщения для всех ошибок валидации.
Html.ValidationSummary(bool) Если параметр bool содержит true, то отображаются только ошибки уровня модели (см. пояснение после таблицы). Если параметр содержит false, то отображаются все ошибки.
Html.ValidationSummary(string) Отображает сообщение (содержащееся в параметре string) перед сообщениями обо всех ошибках валидации.
Html.ValidationSummary(bool, string) Отображает сообщение перед сообщениями об ошибках валидации. Если параметр bool содержит true, то отображаются только ошибки уровня модели.

С другой стороны, ошибки уровня модели можно использовать, если проблемы возникают из-за взаимодействия двух и более значений свойств. Простой пример: давайте представим, что клиенту по имени Джо нельзя записываться на прием по понедельникам. В листинге 23-7 показано, как для этого правила можно создать явное условие валидации в методе действия MakeBooking и вывести сообщение об ошибке валидации уровня модели.

Листинг 23-7: Ошибка валидации уровня модели
[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.IsValidField("ClientName") && ModelState.IsValidField("Date")
			&& appt.ClientName == "Joe" && appt.Date.DayOfWeek == DayOfWeek.Monday)
	{
		ModelState.AddModelError("", "Joe cannot book appointments on Mondays");
	}

	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.IsValidField, что значения свойств ClientName и Date действительны.

Это означает, что мы не будем генерировать ошибку уровня модели, пока не проведем успешную валидацию предыдущих свойств. Чтобы зарегистрировать ошибку уровня модели, мы передаем пустую строку ("") в качестве первого параметра в метод ModelState.AddModelError, например:

ModelState.AddModelError("", "Joe cannot book appointments on Mondays");

Далее мы обновим файл MakeBooking.cshtml, чтобы использовать в нем версию вспомогательного метода ValidationSummary, которая принимает параметр bool и будет отображать только ошибки уровня модели, как показано в листинге 23-8.

Листинг 23-8: Обновляем представление MakeBooking.cshtml, чтобы отображать только ошибки уровня модели
@model ModelValidation.Models.Appointment

@{
	ViewBag.Title = "Make A Booking";
}

<h4>Book an Appointment</h4>

@using (Html.BeginForm())
{
	@Html.ValidationSummary(true)
	<p>Your name: @Html.EditorFor(m => m.ClientName)</p>
	<p>Appointment Date: @Html.EditorFor(m => m.Date)</p>
	<p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms & conditions</p>
	<input type="submit" value="Make Booking" />
}

Результат этих изменений показан на рисунке 23-4, где мы ввели имя Джо и указали дату, которая выпадает на понедельник.

Рисунок 23-4: Отображение сообщения валидации для ошибок уровня модели

Как видно из рисунка, есть две ошибки валидации. Первая - это ошибка уровня модели, которая возникает, когда Джо пытается записаться на прием в понедельник. Вторая появляется из-за того, что не отмечен чекбокс для условий пользовательского соглашения. Так как в сообщении валидации мы отображаем только ошибки уровня модели, пользователь не увидит никаких сведений о второй проблеме.

Отображаем сообщения валидации уровня свойства

Мы отображаем только сообщения об ошибках уровня модели потому, что ошибки уровня свойства можно отображать рядом с соответствующими полями. Таким образом, мы не хотим дублировать сообщения, относящиеся к отдельным свойствам. В листинге 23-9 показано обновленное представление MakeBooking.cshtml, которое отображает ошибки уровня модели сверху и ошибки уровня свойства рядом с соответствующим полем ввода.

Листинг 23-9: Используем сообщения об ошибках для конкретного свойства
@model ModelValidation.Models.Appointment

@{
	ViewBag.Title = "Make A Booking";
}

<h4>Book an Appointment</h4>

@using (Html.BeginForm())
{
	@Html.ValidationSummary(true)
	<p>@Html.ValidationMessageFor(m => m.ClientName)</p>
	<p>Your name: @Html.EditorFor(m => m.ClientName)</p>
	<p>@Html.ValidationMessageFor(m => m.Date)</p>
	<p>Appointment Date: @Html.EditorFor(m => m.Date)</p>
	<p>@Html.ValidationMessageFor(m => m.TermsAccepted)</p>
	<p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms & conditions</p>
	<input type="submit" value="Make Booking" />
}

Вспомогательный метод Html.ValidationMessageFor отображает ошибки валидации для одного свойства модели. Результат его применения в представлении MakeBooking показан на рисунке 23-5.

Рисунок 23-5: Используем вспомогательный метод для отображения сообщений валидации для одного свойства
или RSS канал: Что новенького на smarly.net