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

145

В статье Атрибуты привязки модели было показано, как использовать атрибуты проверки достоверности вместе со средством привязки моделей, чтобы гарантировать отправку пользователем допустимых данных при создании объектов моделей. В случае возникновения любых проблем с данными форма отображается пользователю заново и содержит сводку по обнаруженным ошибкам. После этого пользователь имеет возможность устранить проблемы и повторно отправить форму.

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

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

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

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

Пример проекта

Мы продолжим работу с проектом ClientDev, созданным в предыдущих статьях, но сначала должны внести в него несколько изменений, которые связаны с темами, рассматриваемыми далее. Прежде всего, понадобится добавить ряд атрибутов проверки достоверности в класс модели Game, чтобы указать ограничения, которые должны быть удовлетворены. Применение таких атрибутов демонстрируется в примере:

using System;
using System.ComponentModel.DataAnnotations;

namespace ClientDev.Models
{
    [Serializable]
    public class Game
    {
        public int GameId { get; set; }

        [Required]
        [StringLength(20, MinimumLength=5)]
        public string Name { get; set; }
        public string Description { get; set; }

        [Required]
        public string Category { get; set; }

        [Required]
        [Range(1, 10000)]
        public decimal Price { get; set; }
    }
}

Мы применили атрибуты Requited, StringLength и Range. Атрибут Required используется для указания на обязательность предоставления значений свойствам Name, Price и Category, атрибут StringLength - для указания на то, что значение свойства Name должно содержать от 5 до 20 символов, а атрибут Range - что значение свойства Price должно находиться между 1 и 10000.

Затем мы создаем веб-форму под названием CreateGame.aspx, контент которой представлен в примере:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CreateGame.aspx.cs" Inherits="ClientDev.CreateGame" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title></title>
     <style>
        th { text-align: left; }
        td[colspan="2"] { text-align: center; padding: 10px 0; }
        .error { color: red; }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ValidationSummary runat="server" CssClass="error" />
        <table>
            <tr>
                <td>Название:</td>
                <td><input id="Name" runat="server" /></td>
            </tr>
            <tr>
                <td>Категория:</td>
                <td><input id="Category" runat="server" /></td>
            </tr>
            <tr>
                <td>Цена:</td>
                <td><input id="Price" runat="server" /></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="Добавить игру" runat="server"/></td>
            </tr>
            <tr><th>ID</th><th>Название</th><th>Категория</th><th>Цена</th></tr>
            <asp:Repeater runat="server" 
                    ItemType="ClientDev.Models.Game" SelectMethod="GetCreated">
                <ItemTemplate>
                    <tr>
                        <td><%#: Item.GameId %></td>
                        <td><%#: Item.Name %></td>
                        <td><%#: Item.Category %></td>
                        <td><%#: Item.Price.ToString("F2") %></td>
                    </tr>
                </ItemTemplate>
            </asp:Repeater>
        </table>
    </form>
</body>
</html>

Эта веб-форма содержит элементы <input>, с помощью которых собираются значения, предназначенные для создания новых объектов Game. Элементы <input> помещены внутрь элемента <table>, в котором также находится элемент управления Repeater, используемый для отображения детальных сведений о создаваемых объектах данных. Мы также предусмотрели элемент управления ValidationSummary для вывода сообщений об ошибках привязки модели.

Ниже приведено содержимое файла отделенного кода для веб-формы, в котором обрабатываются элементы <input> и вывод из элемента управления Repeater:

using System;
using System.Collections.Generic;
using System.Web.ModelBinding;
using ClientDev.Models;
using ClientDev.Models.Repository;

namespace ClientDev
{
    public partial class CreateGame : System.Web.UI.Page
    {
        List<Game> CreatedGames;

        protected void Page_Load(object sender, EventArgs e)
        {
            CreatedGames = (List<Game>)ViewState["data"] ?? new List<Game>();
            if (IsPostBack)
            {
                Game newGame = new Game();
                TryUpdateModel<Game>(newGame,
                    new FormValueProvider(ModelBindingExecutionContext));
                if (ModelState.IsValid)
                {
                    new Repository().AddGame(newGame);
                    CreatedGames.Add(newGame);
                    ViewState["data"] = CreatedGames;
                    DataBind();
                }
            }
        }

        public IEnumerable<Game> GetCreated()
        {
            return CreatedGames;
        }
    }
}

В методе Page_Load() выполняется ручная привязка модели для заполнения свойств объекта Game и с помощью состояния представления отслеживаются объекты Game, добавляемые в хранилище. Данные состояния представления используются для наполнения информацией элемента управления Repeater.

Результатом является веб-форма, которая позволяет пользователю создавать объекты Game для хранилища и проверять достоверность предоставляемых данных с помощью атрибутов проверки, примененных к классу Game:

Создание объектов Game с помощью веб-формы CreateGame.aspx

Не забывайте, что данные хранилища в рассматриваемом примере находятся в памяти, поэтому в случае останова или перезапуска приложения изменения будут утеряны.

Веб-форма CreateGame.aspx иллюстрирует типичный пример проверки достоверности серверной стороны. Мы применили атрибуты проверки достоверности к классу Game. Политика, определяемая этими атрибутами, применяется к данным, которые предоставил пользователь, после отправки формы серверу.

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

Для проверки достоверности клиентской стороны понадобится установить дополнительную библиотек JavaScript. Выберите пункт Manage NuGet Packages (Управлять пакетами NuGet) в меню Project (Проект) среды Visual Studio, чтобы открыть окно Manage NuGet Packages (Управление пакетами NuGet). Затем выберите категорию Online (Онлайновые) в левой панели и найдите пакет Microsoft jQuery Unobtrusive Validation. Этот пакет зависит от библиотеки jQueiy (которая уже была установлена) и пакета jQuery.Validation.

Создание пакета сценариев для проверки достоверности

Далее внутрь веб-формы должны быть включены JavaScript-библиотеки jQuery, jQuery Validation и Microsoft jQuery Unobtrusive Validation, поэтому мы определили новый пакет сценариев в файле App_Start\BundleConfig.cs, как показано в примере ниже:

using System;
using System.Web.Optimization;
using System.Web.UI;

namespace ClientDev
{
    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            // ...

            Bundle validation = new ScriptBundle("~/bundle/validation")
                .Include("~/Scripts/jquery-{version}.js",
                    "~/Scripts/jquery.validate.js",
                    "~/Scripts/jquery.validate.unobtrusive.js");

			// ...
			
            bundles.Add(validation);
            
			// ...
        }
    }
}

Итак, подготовительные шаги выполнены, в следующих статьях мы рассмотрим два типа клиентских проверок достоверности - с использованием HTML5 + JavaScript и с использованием встроенных элементов управления ASP.NET.

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