Персональный блог Игоря Антонова aka "spider_net"

Fluent Validation в ASP .NET MVC приложениях. Основы


Рубрика: ASP .NET MVC -> c# -> Программирование
Метки: | |
Просмотров: 10794
Fluent Validation в ASP .NET MVC приложениях. Основы

Валидация данных в ASP .NET MVC приложениях у многих ассоциируется с применением технологии аннотации данных (Data Annotation). Если ты хоть раз подключал для создания проверок пространство имен System.ComponentModel.DataAnnotations , то однозначно понимаешь, о чем я говорю. Технология «Data Annotation» позволяет организовать гибкую проверку моделей. Для самых простых случаев есть предопределенные атрибуты, позволяющие упростить проверку таких вещей как номер телефона, email, длина строки и т.д. Если требуются нестандартные проверки - всегда есть возможность написать собственный валидатор.

Во всех своих ASP .NET MVC проектах я старался использовать именно DataAnnotations, но однажды я наткнулся на библиотеку Fluent Validation и решил познакомиться с ее функционалом. Как оказалось позже, библиотека пользуется популярностью среди англоговорящих разработчиков и многие проверки с ее помощью делать проще, чем с DataAnnotations.

Библиотека доступна для MVC проектов, начиная с третьей версии. Среди киллер фич можно выделить удобство применения, наличие готовых валидаторов из коробки, гибкость разработки своих валидаторов и удобство проверки зависимых полей модели. Например, у нас есть поле «field», значение которого требуется проверять, если «field2» установлено в true. Подобную проверку можно описать одной строчкой кода:

RuleFor(x => x.field).NotEmpty().When(x => x.field2);

Скажу по секрету, изначально именно эта возможность заставила меня сфокусироваться на этой библиотеке и протестировать ее.

Добавляем Fluent Validation к рабочему проекту

Чтобы потренироваться в применении библиотеки Fluent Validation я создал новый ASP .NET MVC4 проект типа Internet Application. Этот тип проекта уже содержит рабочую систему аутентификации/авторизации и готовые страницы для выполнения регистрации и входа на сайт. Проверка всех отправляемых пользователем данных реализована через «DataAnnotation». В рамках данного примера мы попробуем избавится от Data Annotation и воспользоваться услугами библиотеки Fluent Validation.

Итак, для добавления библиотеки Fluent Validation к уже созданному проекту необходимо в консоле «Package Manager Console» необходимо выполнить следующую команду:

Install-Package FluentValidation.MVC4

На момент написания заметки последняя версия библиотеки имела индекс 5.0.0.1. Если команда выполнилась успешно, то в консоле будет выведен текст вроде этого:

PM> Install-Package FluentValidation.MVC4
Attempting to resolve dependency 'FluentValidation (≥ 5.0.0.1)'.
Installing 'FluentValidation.MVC4 5.0.0.1'.
Successfully installed 'FluentValidation.MVC4 5.0.0.1'.
Adding 'FluentValidation.MVC4 5.0.0.1' to Fluent Validtion.
Successfully added 'FluentValidation.MVC4 5.0.0.1' to Fluent Validtion.

Выбираем модель для опытов

Для первоначальной демонстрации библиотеки Fluent Validation, попробуем избавить одну из моделей тестового проекта от DataAnnotation. Открываем файл AccountModels (в нем описаны все модели) и находим код модели RegisterModel. Код, сгенерированный Visual Studio приведен ниже:

public  class  RegisterModel
{
 [Required]
 [Display (Name =  "User name" )]
 public string UserName { get; set; }
 [Required]
 [StringLength (100, ErrorMessage =  "The {0} must be at least {2} characters long.", MinimumLength = 6)]
 [DataType(DataType.Password)]
 [Display(Name =  "Password")]
 public  string  Password { get; set; }
 [DataType(DataType.Password)]
 [Display (Name =  "Confirm password")]
 [Compare("Password", ErrorMessage =  "The password and confirmation password do not match.")]
 public  string  ConfirmPassword { get; set; }
}

Из кода видно, что для каждого поля установлен соответствующий атрибут валидации. Таким образом, поля модели RegisterModel должны быть в обязательном порядке заполнены (атрибут Required) . Поле с паролем должно содержать минимум 6 символов, а общая длина строки не должна превышать 100 символов (атрибуты StringLength и MinimumLength). Для поля ConfirmPassword используется атрибут Compare, который указывает на необходимость сравнения значения поля ConfirmPassword со значением поля Password (пароли же должны совпадать).

Заменяем DataAnnotation на Fluent Validation

Попробуем переписать рассмотренный выше пример с применением Fluent Validation. Для этого создадим новый класс RegisterModelValidator():

using  FluentValidation;
namespace  Fluent_Validtion.Models.Validators
{
  public class RegisterModelValidator : AbstractValidator <RegisterModel>
  {
   public  RegisterModelValidator()
        {
            RuleFor(x => x.UserName)
                   .NotNull();
            RuleFor(x => x.Password)
                   .NotNull()
                   .Length(6, 100);
            RuleFor(x => x.ConfirmPassword)
                    .Equal(x => x.Password);
        }
    }
}

В конструкторе класса RegisterModelValidator описываются правила для проверки свойств модели. Пример демонстрирует установку следующих правил:

  • Поле UserName не может быть Null (NotNull());
  • Поле Password должно содержать минимум 6 символов и размер строки не должен превышать 100 символов (Length());
  • Значение поля ConfirmPassowrd должно быть равно значению из поля Password;
  • Инициализируем валидатор

    Валидатор на базе Fluent Validation полностью готов, теперь его необходимо подключить к проверяемой модели. Делается это путем добавления атрибута FluentValidation.Attributes.Validator() :

    using  FluentValidation;
    using  Fluent_Validtion.Models.Validators;
    [FluentValidation.Attributes. Validator( typeof( RegisterModelValidator))]
     public  class  RegisterModel
     {       
        [Display (Name =  "User name")]
        public  string  UserName { get; set; }
                    
        [DataType(DataType.Password)]
        [Display (Name =  "Password")]
        public  string  Password {  get ;  set; }
        [DataType(DataType.Password)]
        [Display (Name =  "Confirm password")]       
        public  string  ConfirmPassword {  get ;  set; }
    }

    В выше приведенном коде я убрал все атрибуты DataAnnotation и добавил к модели созданный нами валидатор. Модифицированный проект почти готов к старту, остается лишь прописать вызов инициализации Fluent Validation в Application_Start(), объявленный в файле Global.asax:

    using  FluentValidation.Mvc;
    namespace  Fluent_Validtion
    {
       public class MvcApplication : System.Web.HttpApplication
       {
          protected void Application_Start()
          {
            AreaRegistration .RegisterAllAreas();
            WebApiConfig .Register( GlobalConfiguration  .Configuration);
            FilterConfig .RegisterGlobalFilters( GlobalFilters  .Filters);
            RouteConfig .RegisterRoutes( RouteTable  .Routes);
            BundleConfig .RegisterBundles( BundleTable  .Bundles);
            AuthConfig .RegisterAuth();
            //Выполняем инициализацию Fluent Validation
            FluentValidationModelValidatorProvider .Configure();
          }
       }
    }

    Теперь можно запускать пример и тестировать работу библиотеки Fluent Validation на практике. Визуально все работает отлично и теперь можно переходить к следующему шагу – написанию Unit-тестов, но об этом мы поговорим в следующей части заметки.

    Обрати внимание, в шаблоне проекта типа Internet Application включена валидация данных на клиенте. Если ты специально введешь неправильные данные, то тест работы Fluent Validation будет не удачным, т.к. сработает проверка на клиенте. Перед запуском проекта отключи проверку данных на клиенте путем внесения изменений в Web.config:

    <add key = "ClientValidationEnabled" value = "false" />
    <add key = "UnobtrusiveJavaScriptEnabled" value ="false" />
    Комментариев: 2 RSS

    А где продолжение? Когда будут остальные части и будут ли вообще?

    Продолжение обязательно будет. Блог только запущен и сейчас находится в стадии наполнения. По FluentValidaion уже готовы две заметки. Одна из них будет опубликована на следующей неделе. Следи за новостями ;-)

    Оставьте комментарий!
    comments powered by HyperComments