Как стать автором
Обновить

MVC 2: Валидация модели

Время на прочтение 9 мин
Количество просмотров 16K
Автор оригинала: Scott Gu
asp.net mvc 2
Это вторая часть из цикла статей о грядущих нововведениях в ASP.NET MVC 2, выход которого уже не за горами. Данный пост посвящен улучшениям в валидации, добавленных в ASP.NET MVC 2.

ASP.NET MVC 2 валидация


Валидация пользовательских данных, жизненно важная бизнес-логика и правила — ключевое требование большинства веб-приложений. ASP.NET MVC 2 предлагает массу новых возможностей, которые значительно облегчают реализацию валидации пользовательских данных и логики валидации моделей и моделей представления. Новый функционал разработан ориентируясь на обязательную валидацию на стороне сервера, но так же дополнительно может быть реализован на стороне клиента, используя JavaScript. Инфраструктура валидации и функционал в ASP.NET MVC 2 реализован следующим образом:
1) Разработчики могут легко воспользоваться DataAnnotation валидацией, встроенной в .NET Framework. DataAnnotation позволяют, в легкий способ, декларативно добавить правила валидации объектам и свойствам, используя минимальное количество кода.

2) Разработчики могут дополнительно интегрировать свой движок валидации или воспользоваться сторонними фреймворками: Castle Validator, EntLib Validation Library. Возможности валидации ASP.NET MVC 2 разработаны с учетом легкости расширения архитектуры валидации.

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

Подключение валидации в ASP.NET MVC 2 и DataAnnotation


Давайте рассмотрим простой CRUD-сценарий, где воспользуемся новым функционалом — DataAnnotation. Конкретно, создадим форму «Create», которая будет добавлять друга пользователю:

image

До сохранения в базу данных, мы хотим убедиться, что введенная информация корректна, а если нет — вывести соответствующее сообщение об ошибке:

image

Мы хотим, чтобы валидация происходила на двух сторонах — сервере и клиенте, а также хотим удостовериться, что код соответствует принципу DRY(“don’t repeat yourself”) — мы применяем правила валидации один раз, после этого все контроллеры, действия и представления соблюдают их.

Я реализую данный сценарий, используя VS 2010, но вы так же сможете это сделать и в VS 2008.

Шаг 1: Создаем FriendsController (для начала, без валидации)


Начнем с добавления простого класса «Person» в новый проект ASP.NET MVC 2:

image

У класса четыре свойства, созданные при помощи автоматически реализуемых свойств в C#, которые появились и в VB с VS 2010.

Добавим в наш проект класс-контроллер «FriendsController», который расширим двумя методами действий «Create». Первый метод вызывается во время GET запроса /Friends/Create — он отобразит пустую форму для ввода данных о человеке. Второй метод вызывается во время POST запроса /FriendsCreate — он привязывает введенные данные формы к объекту Person, проверяет на наличие ошибок при связывании и, если ошибок не произошло, в конечном итоге сохраняет в базу данных (саму реализацию работы с базой данных реализуем чуть позже). Если введенные данные в форму содержат ошибки, метод вернет пользователю форму с ошибками:

image

После создания нашего контроллера, мы можем нажать правой кнопкой по одному из методов действия и выбрать «Add View», мы воспользуемся скафолдингом для создания «Create» представления, которое принимает объект Person:

image

Visual Studio сгенерирует для нас файл представления Create.aspx в директории \Views\Friends нашего проекта. Обратите внимание на использование строго типизированных HTML вспомогательных методов:

image

А сейчас, когда мы запустим приложение и перейдем на /Friends/Create, то получим пустую форму для ввода данных:

image

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

Шаг 2: Добавляем валидацию, используя DataAnnotation


Усилим наше приложение простыми правилами валидации входящих данных. Мы внедрим данные правила в модели Person, а не в контроллере или представлении. Данный подход обеспечит валидацию при любых сценариях в нашем приложении, где используется объект Person (например, если мы добавим сценарий редактирования), а также обеспечит соответствие кода принципу DRY и избавит от дублирования правил в разных участках кода.

В ASP.NET MVC 2 разработчики могут легко добавлять декларативные атрибуты валидации в классы модели или модели представления, которые в дальнейшем используются при операции связывании с моделью. Чтобы увидеть это в действии, давай-те обновим класс Person, добавив несколько атрибутов. Добавим определение «using» для пространства имен “System.ComponentModel.DataAnnotations”, а далее оформим свойства Person, используя атрибуты валидации [Required], [StringLength], [Range] и [RegularExpression]

image
Обратите внимание на объявление текста ошибок, как строк. Вы можете объявить их в файлах ресурсов и локализировать в зависимости от выбранного пользователем языком или культурой. Более детально о локализации ошибок валидации тут.

И вот, когда у нас добавлены атрибуты валидации в класс Person, давайте перезапустим наше приложение, чтобы увидеть реакцию на некорректно введенные данные, отправив их на сервер:

image

Заметили, как у нас все стало прилично? Текст ошибки подсечен красным, а сама ошибка выведена рядом с полем. Форма сохраняет введенный данные, так что мы избавляем пользователя от нужды вводить их повторно. И как же, черт побери, все это происходит?

Чтобы понять принцип работы, давайте взглянем на метод действия Create, который обрабатывает POST запрос нашей формы:

image

Когда наша HTML форма возвращает данные серверу, вызывается выше приведенный метод. Так как метод действия принимает объект Person, как параметр, ASP.NET MVC создаст объект Person и автоматически свяжет входящие данные формы с его значениями. Так же, как часть данного процесса, произойдет проверка на соответствие правилам валидации DataAnnotation объекта Person. В случае удачной проверки, ModelState.IsValid вернет true и мы сохраним результат в базу и перекинем пользователя на home-страницу.

Если произойдет любая ошибка валидации, наш метод действия вновь отобразит форму с не правильными данными объекта Person. Это реализовывается с помощью последней строки в приведенном выше коде.

Сообщения об ошибках отображаются на странице благодаря вспомогательному методу <%= Html.ValidationMessageFor() %> после каждого <%= Html.TextBoxFor() %> в форме Create. Вспомогательный метод Html.ValidationMessageFor() отобразит соответствующее сообщение об ошибке для любого не валидного свойства модели, переданного в представление:

image

Удобство данного паттерна в простоте внедрения в код, а также простота в добавлении или изменении правил валидации нашего класса Person, без надобности изменять код за пределами модели. Возможность определить правила валидации в одном месте и принудительное использование данных правил в любом уголке приложения позволяет нам быстро развивать наше приложение с минимальными усилиями, при это избегая дублирование кода.

Шаг 3: Добавление валидации на стороне клиента


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

Одной из вкусностей в ASP.NET MVC 2 является архитектура валидации, которая поддерживает проверку на сервере и на клиенте. Для этого нам всего-лишь нужно добавить два JavaScript скрипта в представлении и написать одну строчку кода:

image

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

Чтобы увидеть проверку на клиенте в действии, перезапустим приложение и заполним первые три текстовых поля корректными данными, а далее попробуем нажать «Create». Заметьте каким образом мы получили информацию об ошибке, никакой отправки данных на сервер не произошло:

image

Если мы введем текст, который не является корректным адресом электронной почты, то ошибка сразу изменится с «Email required» на «Not a valid email», оба сообщения мы объявили ранее в классе Person:

image

Когда же мы введем корректный адрес электронной почты — сообщение об ошибке исчезнет и фон текстового поля вернется в нормальное состояние:

image

Нам не нужно писать никакого собственного JavaScript кода для добавления логики валидации. Наш код до сих пор соответствует принципу DRY.

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

Клиентская JavaScript валидация может работать с любым фреймворком/движком, который вы используете с ASP.NET MVC. Нет ограничений в использовании DataAnnotation, вся инфраструктура работает независимо от DataAnnotation и может работать с Castle Validator, EntLib Validation Block или любым другим решением.

Если вы не желаете использовать наши JavaScript файлы, вы можете заменить их на плагин валидации jQuery и использовать его. Дополнение ASP.NET MVC Futures будет включать в себя поддержку jQuery валидации.

Шаг 4: Создание собственного(email) атрибута валидации


Пространство имен System.ComponentModel.DataAnnotations содержит несколько встроенных атрибутов валидации, которые вы можете использовать. Мы уже использовали четыре — [Required], [StringLength], [Range] и [RegularExpression].

Но вы можете объявить свой собственный атрибут валидации и использовать его. Вы можете создать полностью новый атрибут наследуясь от класса ValidationAttribute, который находится в пространстве имен System.ComponentModel.DataAnnotations. А можете создать атрибут на основе существующих, если хотите просто расширить их функциональность.

Например, для поддержания чистоты кода в нашем классе Person мы хотим создать новый атрибут валидации [Email], который инкапсулирует регулярное выражение для проверки электронных адресов. Простой способ — унаследоваться от класса RegularExpression и вызывать конструктор класса RegularExpression с соответствующим регулярным выражением:

image

Теперь мы можем обновить класс Person и использовать наш новый атрибут валидации [Email] взамен предыдущего регулярного выражения, согласитесь — код стал чище:

image

Когда вы создаете собственный атрибут валидации, то можете определить правила проверок на сервере и клиенте.

Напоследок, для создания собственных атрибутов, которые обращаются к индивидуальным свойства объекта, вы можете обращаться к атрибутам валидации на уровне класса. Это позволяет вам реализовать логику в связке с несколькими свойствами в объекте. Например, можете посмотреть на атрибут «PropertiesMustMatchAttribute», который находится в файле AccountModels.cs/vb в стандартном шаблоне приложения ASP.NET MVC 2 (File>New ASP.NET MVC 2 Web Project в VS 2010).

Шаг 5: Переходим к базе даных


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

image

Сейчас мы используем с C# класс старого образца (часто называемыем, как «POCO» класс — «plain old CLR object»). Один из подходов — написать отдельно код, который привязывает существующий класс к базе данных. На сегодняшний день, такие решения на основе объектно-реляционной проекции (ORM), как NHibernate отлично поддерживают стиль POCO связи. ADO.NET Entity Framework (EF), который выйдет с .NET 4 так же поддерживает POCO связи и, как NHibernate, дополнительно поддерживает возможность связи через код, не используя файлов связи или конструтора.

Если наш объект Person был связан с базой данных одним из перечисленных способов, то нам не нужно вносить никаких изменений в класс Person.

А что если мы используем визуальный инструмент для наших ORM-связей?

Сегодня, многие разработчики использующие Visual Studio не пишут собственную ORM-логику связей, а используют встроенные в VS конструкторы, чтобы решить данную проблему.

Часто возникает вопрос при использовании DataAnnotation (или любой другой формы атрибутов, основанных на валидации) — «как вы примените правила, когда модель объекта, с который вы работаете, создана с помощью GUI конструктор?». Например, если мы взамен класса Person, оформленного в стиле POCO, создадим класс Personal в Visual Studio, используя GUI-интсрумент связей — LINQ to SQL или ADO.NET EF:

image

На скриншоте вы видите класс Person, объявленный с помощью конструктора ADO.NET EF в VS 2010. Верхнее окно определяет класс Person, нижнее — отображает редактор связей, а именно, как свойства привязываются к таблице базы данных «People». После сохранение автоматически сгенерируется класс Person. Это удобно, за исключением того, что при каждом изменении вам нужно будет сохранять файл, что приведет к полной перегенерации класса Person и вы потеряете все объявленные атрибуты валидации.

Решение, которое поможет применить к автоматически созданному классу дополнительные метаданные атрибутов — дружественные классы. Фактически — вы создаете отдельный класс, который содержит ваши атрибуты валидации и метаданных, а далее привязываете его к сгенерированному классу, применяя атрибут «MetadataType» к сгенерированному partial-классу. Например, мы хотим применить правила валидации, которые использовали ранее, к классу Person, созданному с помощью конструктора LINQ to SQL или ADO.NET EF, для этого вынесем наш код валидации в класс «Person_Validation» и свяжем его с классом «Person»:

image

Данный вариант уступает в элегантности варианту POCO, но у него преимущество в работе с большинством инструментов или с сгенерированным конструкторами кодом в Visual Studio.

Последний шаг — Сохранение Friend в базу данных.


Наш последний шаг, в не зависимости от подхода, который мы использовали: POCO или сгенерированный каким-то инструментом класс Person, будет сохранением валидных объектов Friend в базу данных.

Для этого заменяем «Todo» метку в классе FriendsController тремя строчками кода, которые будут сохранять нового друга в базу данных. Ниже представлена полная версия класса FriendsController, который работает с ADO.NET EF:

image

Теперь, когда мы посетим URL /Friends/Create, то сможем легко добавить новый объект People в список наших друзей в базе данных:

image

Валидация всех данных происходит на клиенте и на сервере. Мы можем легко добавлять/изменять/удалять правила валидации и они будут использованы в обязательном порядке любым контроллером или представлением в наше приложении.

Подведем итоги


ASP.NET MVC 2 позволяет гораздо проще интегрировать валидацию в веб-приложения. Предлагает подход в валидации, основанный на моделях, что позволяет избежать дублирования кода в разных местах, а также позволяет быть уверенным, что правила валидации будут гарантированно использованы во всем приложении. Встроенная поддержка DataAnnotation, позволяет реализовывать распространенные варианты валидации прямо из коробки. Поддержка расширяемости инфраструктуры валидации позволяет реализовывать различные сценарии проверок и подключать любые фреймворки валидации.
Теги:
Хабы:
+11
Комментарии 13
Комментарии Комментарии 13

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн