Клиентская проверка достоверности

70

Продемонстрированные до сих пор технологии проверки являются примерами проверки достоверности на стороне сервера. Это означает, что пользователь отправляет данные серверу, после чего сервер их проверяет и посылает обратно результаты проверки (либо признак успешности, либо список ошибок, подлежащих исправлению).

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

Инфраструктура ASP.NET MVC Framework поддерживает ненавязчивую проверку достоверности на стороне клиента. Термин "ненавязчивая" означает, что правила проверки выражаются с использованием атрибутов, которые добавляются к HTML-элементам, сгенерированным представлениями. Эти атрибуты интерпретируются JavaScript-библиотекой, входящей в состав ASP.NET MVC Framework, которая, в свою очередь, конфигурирует библиотеку jQuery Validation, выполняющую всю работу по проверке достоверности. В последующих разделах будет показано, как работает встроенная поддержка проверки достоверности, и продемонстрированы способы расширения ее функциональности для предоставления проверки достоверности на стороне клиента.

Проверка достоверности на стороне клиента сосредоточена на проверке достоверности индивидуальных свойств. В действительности настроить проверку на стороне клиента на уровне модели с помощью встроенной в ASP.NET MVC Framework поддержки довольно трудно. В связи с этим в большинстве приложений MVC проверка на стороне клиента используется для свойств, а проверка на стороне сервера - для всей модели.

Включение и отключение проверки достоверности на стороне клиента

Проверка достоверности на стороне клиента управляется двумя настройками в файле Web.config, как показано в примере ниже:

...
<appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
...

Чтобы проверка на стороне клиента заработала, обе эти настройки ClientValidationEnabled и UnobtrusiveJavaScriptEnabled должны быть установлены в true. При создании нового проекта MVC среда Visual Studio добавляет эти настройки и устанавливает их в true.

Конфигурировать проверку достоверности на стороне клиента можно также для отдельных представлений, устанавливая свойства HtmlHelper.ClientValidationEnabled и HtmlHelper.UnobtrusiveJavaScriptEnabled в блоке кода Razor.

Установка пакетов NuGet

Обеспечение генерации инфраструктурой ASP.NET MVC Framework атрибутов, требуемых для проверки достоверности, является лишь одной частью процесса настройки. Необходимо также добавить пакеты JavaScript, которые обрабатывают эти атрибуты и проверяют данные, введенные пользователем в форму. Все нужные пакеты доступны через NuGet, поэтому выберите пункт меню Tools --> Library Package Manager --> Package Manager Console (Сервис --> Диспетчер библиотечных пакетов --> Консоль диспетчера пакетов), чтобы открыть окно командной строки NuGet, и введите следующие команды:

Install-Package jQuery -version 1.10.2 -projectname ModelValidation
Install-Package jQuery.Validation -version 1.11.1 -projectname ModelValidation
Install-Package Microsoft.jQuery.Unobtrusive.Validation -version 3.0.0 -projectname ModelValidation

Указанные пакеты помещают в папку Scripts файлы, которые затем понадобится добавить в компоновку _Layout.cshtml с помощью элементов <script>, как показано в примере ниже:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title</title>
    <style>
        ...
    </style>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.validate.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

Использование проверки достоверности на стороне клиента

После включения проверки достоверности на стороне клиента и обеспечении ссылок на JavaScript-библиотеки в компоновке можно приступать к проведению проверки на стороне клиента. Простейший способ сделать это - применить атрибуты метаданных, которые ранее использовались для проверки достоверности на стороне сервера, такие как Required, Range и StringLength.

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

using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using ModelValidation.Infrastructure;

namespace ModelValidation.Models
{
    public class Appointment
    {
        [Required(ErrorMessage = "Введите свое имя")]
        [StringLength(10, MinimumLength= 3)]
        public string ClientName { get; set; }

        [DataType(DataType.Date)]
        public DateTime Date { get; set; }

        public bool TermsAccepted { get; set; }
    }
}

Это все, что необходимо сделать для запуска в работу базовой проверки достоверности на стороне клиента. Мы применили несколько другое сочетание встроенных атрибутов проверки достоверности, чтобы можно было продемонстрировать ряд возможностей проверки на стороне клиента, но с учетом включения JavaScript-библиотек в HTML-разметку, отправляемую клиенту, они нормально работают.

Чтобы оценить эффект от проверки достоверности на стороне клиента, запустите приложение, перейдите на URL вида /Home/MakeBooking и введите одну букву в поле для имени. Нажмите клавишу <Tab> или щелкните на другом элементе ввода, и вы немедленно увидите сообщение проверки, сгенерированное JavaScript-кодом, который выполняется в браузере:

Немедленный отклик от средства проверки достоверности на стороне клиента

В примере выше к свойству ClientName применяется атрибут проверки достоверности StringLength, и он вызывает генерацию сообщения об ошибке, как показано на рисунке выше. Этот отклик появляется немедленно и никаких запросов к серверу не отправляется. В действительности JavaScript-код, выполняющий проверку достоверности, будет препятствовать отправке формы до тех пор, пока в ней не останется ошибок проверки.

Когда пользователь исправит ошибку, отклик также будет немедленным. Если продолжить ввод в поле для имени, сообщение об ошибке исчезнет, как только длина введенного имени превысит три символа. Но если продолжить ввод вплоть до одиннадцатого символа, снова отобразится сообщение об ошибке. Причина в том, что для свойства ClientName с помощью атрибута StringLength была указана минимальная длина в три, а максимальная - в десять символов. Такой вид динамического отклика помогает пользователю предоставлять данные, требуемые приложению, без необходимости в отправке формы серверу и ожидания от него ответа.

Особенности работы проверки достоверности на стороне клиента

Одно из преимуществ использования проверки достоверности на стороне клиента в ASP.NET MVC Framework - отсутствие необходимости писать какой-либо код JavaScript. Вместо этого правила проверки достоверности выражаются с помощью атрибутов HTML. Ниже показана HTML-разметка, генерируемая вспомогательным методом Html.EditorFor() для свойства ClientName, когда проверка достоверности на стороне клиента отключена:

...
<input class="text-box single-line" id="ClientName" name="ClientName" 
       type="text" value="" />
...

А вот как выглядит HTML-разметка для того же самого свойства при включенной проверке достоверности на стороне клиента:

...
<input class="text-box single-line" id="ClientName" name="ClientName" 
       type="text" value=""
	   data-val="true" 
	   data-val-length="Поле ClientName должно быть строкой с минимальной длиной 3 и максимальной 10."
	   data-val-length-max="10" 
	   data-val-length-min="3" 
	   data-val-required="Введите свое имя" />
...

Поддержка проверки достоверности на стороне клиента MVC не генерирует какой-либо код JavaScript или данные JSON для управления процессом проверки; как и в большинстве частей инфраструктуры ASP.NET MVC Framework, проверка достоверности опирается на соглашение. Первым добавленным атрибутом является data-val. Библиотека jQuery Validation идентифицирует поля, требующие проверки достоверности, по наличию этого атрибута.

Отдельные правила проверки достоверности указываются с использованием атрибута в формате data-val-<имя>, где <имя> - это правило, подлежащее применению. Таким образом, например, атрибут Required, примененный к классу модели, в результате даст атрибут data-val-required в HTML-разметке.

Значение, связанное с атрибутом, представляет собой сообщение, ассоциированное с правилом. Некоторые правила требуют дополнительных атрибутов. Это можно видеть в правиле длины, которое имеет атрибуты data-val-length-min и data-val-length-max, позволяющие задавать минимально и максимально допустимую длину строки. Интерпретация правил проверки, связанных с обязательностью и длиной, обеспечивается библиотекой jQuery Validation, на основе которой построены средства проверки достоверности на стороне клиента в MVC.

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

Избегание конфликтов с проверкой достоверности, встроенной в браузеры

Ряд браузеров текущего поколения, поддерживающих HTML5, обеспечивают простую проверку достоверности на стороне клиента, которая основана на атрибутах, примененных к элементам <input>. Общая идея заключается в том, что элемент <input>, к которому применен атрибута required, например, вызовет отображение браузером сообщения об ошибке проверки достоверности, если пользователь попытается отправить форму, не предоставив значение для этого элемента.

В случае генерации элементов форм из моделей, как это делалось в наших примерах, никаких проблем со встроенной в браузеры проверкой достоверности возникать не будет, поскольку для обозначения правил проверки инфраструктура ASP.NET MVC Framework генерирует и использует атрибуты данных (таким образом, например, элемент <input>, который должен иметь значение, снабжается атрибутом data-val-required, не распознаваемым браузерами атрибутом required).

Тем не менее, вы можете столкнуться с проблемами, если не в состоянии полностью контролировать разметку в приложении, что часто происходит при поступлении содержимого, сгенерированного в другом месте. В результате форма может быть обработана одновременно средствами проверки достоверности как и библиотеки jQuery, так и встроенными в браузер, что приведет к путанице. Во избежание проблемы подобного рода к элементу <form> можно добавить атрибут novalidate.

Выполнение удаленной проверки достоверности

В завершение этой статьи мы рассмотрим удаленную (дистанционную) проверку достоверности. Это прием проверки достоверности на стороне клиента, при котором для выполнения проверки вызывается метод действия на стороне сервера.

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

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

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

Таким образом, удаленная проверка достоверности является компромиссом. Она позволяет соблюсти баланс между проверками на стороне клиента и на стороне сервера, но требует выполнения запросов к серверу приложений, поэтому в результате не будет настолько быстрой, как обычная проверка достоверности на стороне клиента.

Первый шаг в сторону использования удаленной проверки достоверности предусматривает создание метода действия, который может проверить одно из свойств модели. Мы собираемся проверять свойство Date модели Appointment, чтобы обеспечить нахождение запрошенной даты встречи в будущем. (Это одно из исходных правил проверки достоверности, применяемых ранее, но которое невозможно реализовать с помощью стандартных средств проверки на стороне клиента.) В примере ниже приведен код метода действия ValidateDate(), добавленного в контроллер Home:

using System;
using System.Web.Mvc;
using ModelValidation.Models;

namespace ModelValidation.Controllers
{
    public class HomeController : Controller
    {
        // ...

        public JsonResult ValidateDate(string Date)
        {
            DateTime parsedDate;

            if (!DateTime.TryParse(Date, out parsedDate))
            {
                return Json("Пожалуйста, введите дату в формате (мм.дд.гггг)",
                    JsonRequestBehavior.AllowGet);
            }
            else if (DateTime.Now > parsedDate)
            {
                return Json("Введите дату относящуюся к будущему",
                    JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(true, JsonRequestBehavior.AllowGet);
            }
        }
	}
}

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

Можно было бы воспользоваться привязкой моделей, и тогда параметром метода действия был бы объект DateTime, но в этом случае метод проверки достоверности не вызывался бы в ситуации, когда пользователь вводит бессмысленное значение вроде строк, например. Причина в том, что связыватель модели не сможет создать объект DateTime из строки и сгенерирует исключение. Средство удаленной проверки достоверности не умеет обрабатывать это исключение, потому исключение будет просто отброшено. Это приведет к нежелательному эффекту - поле данных не подсвечивается, создавая впечатление, что введенное пользователем значение является допустимым. Как правило, наилучший подход к удаленной проверке достоверности предусматривает прием параметра string в методе действия и явное выполнение любого преобразования типа, разбора или привязки модели.

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

return Json(true, JsonRequestBehavior.AllowGet);

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

return Json("Введите дату относящуюся к будущему",
	JsonRequestBehavior.AllowGet);

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

Для использования метода удаленной проверки достоверности к интересующему свойству в классе модели применяется атрибут Remote. В примере ниже демонстрируется применение этого атрибута к свойству Date:

using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace ModelValidation.Models
{
    public class Appointment
    {
        [Required(ErrorMessage = "Введите свое имя")]
        [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; }
    }
}

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

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

Выполнение удаленной проверки достоверности

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

Пройди тесты
Лучший чат для C# программистов