Главная страница   /   23.6. Выполнение удаленной валидации (ASP.NET MVC 4

ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

23.6. Выполнение удаленной валидации

Последняя функция валидации, которую мы рассмотрим в этой главе, - это удаленная валидация. Это техника валидации на стороне клиента, которая для выполнения валидации вызывает метод действия на сервере.

Распространенный пример удаленной валидации - это проверка доступности имени пользователя в приложениях, где такие имена должны быть уникальными; пользователь отправляет данные, и выполняется валидация на стороне клиента. Как часть этого процесса на сервер отправляется запрос Ajax, с помощью которого проводится валидация указанного имени пользователя. Если имя занято, то отображается ошибка валидации, чтобы пользователь мог ввести другое значение.

Это похоже на обычную валидацию на стороне сервера, но у этого подхода есть некоторые преимущества. Во-первых, удаленная валидация проводится только для отдельных свойств; преимущества валидации на стороне клиента все еще сохраняются для всех других значений данных. Во-вторых, запрос относительно легкий и ориентирован на валидацию, а не обработку всего объекта модели. Это означает, что мы можем сократить затраты производительности, которые требуются для этого запроса.

Третье отличие состоит в том, что удаленная валидация выполняется в фоновом режиме. Пользователь не должен нажимать на кнопку Submit и дожидаться визуализации нового представления. Это влияет на удобство работы с приложением, особенно в случае медленного соединения.

Таким образом, удаленная валидация является компромиссом; она позволяет нам найти баланс между клиентской валидацией и валидацией на стороне сервера. Хотя она не требует запросов к серверу, но и выполняется не так быстро, как обычная валидация на стороне клиента.

Чтобы использовать удаленную валидацию, для начала необходимо создать метод действия, который будет проверять одно из свойств модели. Мы будем проводить валидацию для свойства Date модели Appointment, чтобы гарантировать то, что указанная встреча состоится в будущем (это одно из первых правил валидации, которое мы использовали в начале главы, но его невозможно реализовать с помощью стандартных функций валидации на стороне клиента). В листинге 23-22 показан метод действия ValidateDate, который мы добавили в контроллер Home.

Листинг 23-22: Добавляем метод валидации в контроллер Home
using System;
using System.Web.Mvc;
using ModelValidation.Models;

namespace ModelValidation.Controllers
{
	public class HomeController : Controller
	{
		public ViewResult MakeBooking()
		{
			return View(new Appointment {Date = DateTime.Now});
		}

		[HttpPost]
		public ViewResult MakeBooking(Appointment appt)
		{
			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();
			}
		}

		public JsonResult ValidateDate(string Date)
		{
			DateTime parsedDate;
			if (!DateTime.TryParse(Date, out parsedDate))
			{
				return Json("Please enter a valid date (mm/dd/yyyy)",
					JsonRequestBehavior.AllowGet);
			}
			else if (DateTime.Now > parsedDate)
			{
				return Json("Please enter a date in the future",
					JsonRequestBehavior.AllowGet);
			}
			else
			{
				return Json(true, JsonRequestBehavior.AllowGet);
			}
		}
	}
}

Методы действий, которые поддерживают удаленную валидацию, должны возвращать тип JsonResult, который сообщает MVC Framework, что мы работаем с данными JSON. Кроме результата, метод валидации должен определить параметр с тем же именем, что и проверяемое поле данных. В этом примере это Date. Мы проверяем, возможно ли создать объект DateTime из значения, которое предоставил пользователь, и, если да, проверяем, что дата состоится в будущем.

Подсказка

Мы могли бы использовать связывание данных и сделать параметром нашего метода действия объект DateTime, но в таком случае метод валидации не будет вызван, если пользователь введет что-то совершенно бессмысленное, например apple. Так произойдет потому, что механизм связывания не сможет создать объект DateTime из значения apple и сгенерирует исключение. Функция удаленной валидации не имеет возможности отобразить это исключение, и поэтому оно будет незаметно удалено. В результате поле ввода не будет подсвечено, что создаст впечатление, что введенное пользователем значение является действительным. Лучше всего при работе с удаленной валидацией принять строковый параметр в методе действия и выполнить преобразование, анализ или связывание данных явно.

Мы выражаем результаты валидации с помощью метода Json, который создает результат в формате JSON; этот результат будет проанализирован и обработан скриптом удаленной валидации на стороне клиента. Если обработанное значение отвечает нашим требованиям, то мы передаем true в метод Json в качестве параметра:

return Json(true, JsonRequestBehavior.AllowGet);

Если мы недовольны значением, то в качестве параметра передаем сообщение об ошибке валидации, которое должно быть показано пользователю, например:

return Json("Please enter a date in the future", JsonRequestBehavior.AllowGet);

В обоих случаях мы передаем в качестве параметра значение JsonRequestBehavior.AllowGet, потому что MVC Framework по умолчанию запрещает запросы GET, которые создают JSON, и это поведение необходимо переопределить. Без этого дополнительного параметра запросы валидация будет незаметно опускаться, и ошибки валидации не будет отображаться клиенту.

Чтобы использовать метод удаленной валидации в классе модели, мы применяем атрибут Remote к свойству, которое хотим проверить. В листинге 23-23 показано, как мы применили его к свойству Date.

Листинг 23-23: Используем атрибут Remote в классе модели
using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace ModelValidation.Models
{
	public class Appointment
	{
		[Required]
		[StringLength(10, MinimumLength = 3)]
		public string ClientName { get; set; }

		[DataType(DataType.Date)]
		[Remote("ValidateDate", "Home")]
		public DateTime Date { get; set; }

		public bool TermsAccepted { get; set; }
	}
}

Аргументами для этого атрибута являются имя действия и контроллера для создания ссылки, с помощью которой библиотека валидации JavaScript будет выполнять валидацию; в нашем случае, это действие ValidateDate в контроллере Home.

Чтобы увидеть, как работает удаленная валидация, запустите приложение, перейдите по ссылке /Home/MakeBooking и введите дату, которая произошла в прошлом. Во время ввода появится сообщение валидации, как показано на рисунке 23-12.

Рисунок 23-12: Выполнение удаленной валидации

Внимание!

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