Присвоим стандартные атрибуты свойствам классов Модели разрабатываемого веб-приложения.
Назначаем стандартные атрибуты свойствам Модели
Давайте рассмотрим какие будут сделаны изменения:
Атрибуты [Required] и [StringLength] уже были установлены при указании свойств Модели для Entity Framework. Давайте рассмотрим что еще необходимо к ним добавить.
Начнем с [DataType]. Отметим все свойства типа string как DataType.Text , за исключением следующих:
- BookDetails.Description – многострочный текст: DataType.MultilineText;
- BookDetails.Url и Publisher.Homepage – ссылки на веб-страницу: DataType.Url.
Кроме того, для свойств, содержащих ссылку на сайт, с помощью [RegularExpression] установим регулярное выражение, которое будет проверять корректность введенного текста.
Условимся, что рейтинг книги это число от 1 до 5. Укажем это ограничение для свойства Rating при помощи [Range]. Не забудем добавить соответствующее сообщение об ошибке.
Обратите внимание, что атрибуты четко разделяют ответственность между собой. В данном случае, использование регулярного выражения и ограничение по диапазону не обозначают обязательности ввода значения. Поэтому с точки зрения [RegularExpression] и [Range] значение null является корректным. При необходимости их можно дополнить атрибутом [Required].
Текст сообщений для рассмотренных ошибок добавим в общие ресурсы (ниже в таблице приведены только добавляемые строки):
Файл Resources\Shared\ErrorsRes.resx |
InvalidUrl | Invalid website address. | Не корректный адрес веб-сайта. |
ValueOutOfRange | {0} should be in the range from {1} ... {2}. | Значение вне диапазона. |
В результате файлы классов Модели будет выглядеть так:
namespace BookCatalog.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using BookCatalog.Resources.Models;
using BookCatalog.Resources.Shared;
[Table("Catalog")]
public class BookDetails
{
public int Id { get; set; }
[Display(Name = "Title", ResourceType = typeof(BookDetailsRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[StringLength(128,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Text)]
public string Title { get; set; }
[Display(Name = "Author", ResourceType = typeof(BookDetailsRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[StringLength(128,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Text)]
public string Author { get; set; }
[Display(Name = "Language", ResourceType = typeof(BookDetailsRes))]
[Required(ErrorMessageResourceName = "MustSelectValue",
ErrorMessageResourceType = typeof(ErrorsRes))]
public int LanguageId { get; set; }
public int? PublisherId { get; set; }
[Display(Name = "PublishedAt", ResourceType = typeof(BookDetailsRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Date)]
public DateTime PublishedAt { get; set; }
[Display(Name = "Url", ResourceType = typeof(BookDetailsRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[StringLength(256, MinimumLength = 11,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Url)]
[RegularExpression(@"(http(s)?://)?([\w-]+\.)+[\w-]+(/[\w- ;,./?%&=]*)?",
ErrorMessageResourceName = "InvalidUrl",
ErrorMessageResourceType = typeof(ErrorsRes))]
public string Url { get; set; }
[Display(Name = "Description", ResourceType = typeof(BookDetailsRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[StringLength(512, MinimumLength = 32,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[Display(Name = "Rating", ResourceType = typeof(BookDetailsRes))]
[Range(1, 5,
ErrorMessageResourceName = "ValueOutOfRange",
ErrorMessageResourceType = typeof(ErrorsRes))]
public int? Rating { get; set; }
/// <summary>Gets or sets a value indicating whether
/// the book is free (true) or not (false).</summary>
[Display(Name = "IsFree", ResourceType = typeof(BookDetailsRes))]
public bool IsFree { get; set; }
/// <summary>Gets or sets a value indicating whether
/// the book is visible in the catalog (true) or not (false).</summary>
[Display(Name = "IsVisible", ResourceType = typeof(BookDetailsRes))]
public bool IsVisible { get; set; }
[Display(Name = "Tags", ResourceType = typeof(BookDetailsRes))]
public virtual ICollection<Tag> Tags { get; set; }
[Display(Name = "Language", ResourceType = typeof(BookDetailsRes))]
public virtual Language Language { get; set; }
[Display(Name = "Publisher", ResourceType = typeof(BookDetailsRes))]
public virtual Publisher Publisher { get; set; }
}
}
namespace BookCatalog.Models
{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using BookCatalog.Resources.Models;
using BookCatalog.Resources.Shared;
public class Language
{
public int Id { get; set; }
[Display(Name = "Name", ResourceType = typeof(LanguageRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[StringLength(64, MinimumLength = 2,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Text)]
public string Name { get; set; }
[Display(Name = "Books", ResourceType = typeof(LanguageRes))]
public virtual ICollection<BookDetails> Books { get; set; }
}
}
namespace BookCatalog.Models
{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using BookCatalog.Resources.Models;
using BookCatalog.Resources.Shared;
public class Publisher
{
public int Id { get; set; }
[Display(Name = "Title", ResourceType = typeof(PublisherRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[StringLength(128,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Text)]
public string Title { get; set; }
[Display(Name = "Homepage", ResourceType = typeof(PublisherRes))]
[StringLength(256, MinimumLength = 7,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Url)]
[RegularExpression(@"(http(s)?://)?([\w-]+\.)+[\w-]+(/[\w- ;,./?%&=]*)?",
ErrorMessageResourceName = "InvalidUrl",
ErrorMessageResourceType = typeof(ErrorsRes))]
public string Homepage { get; set; }
[Display(Name = "Books", ResourceType = typeof(PublisherRes))]
public virtual ICollection<BookDetails> Books { get; set; }
}
}
namespace BookCatalog.Models
{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using BookCatalog.Resources.Models;
using BookCatalog.Resources.Shared;
public class Tag
{
public int Id { get; set; }
[Display(Name = "Text", ResourceType = typeof(TagRes))]
[Required(ErrorMessageResourceName = "FieldIsRequired",
ErrorMessageResourceType = typeof(ErrorsRes))]
[StringLength(32, MinimumLength = 2,
ErrorMessageResourceName = "InvalidStringLenght",
ErrorMessageResourceType = typeof(ErrorsRes))]
[DataType(DataType.Text)]
public string Text { get; set; }
[Display(Name = "Books", ResourceType = typeof(TagRes))]
public virtual ICollection<BookDetails> Books { get; set; }
}
}
Запустим веб-приложение. Теперь уже проверяется формат при вводе адресов сайта. Описание книги вводиться в многострочном поле ввода, а при вводе рейтинга необходимо указать число из диапазона.
Но пока что не все ограничения указаны. Например, можно ввести книгу из будущего. Для решения этой проблемы создать свой атрибут, чем и займемся в дальнейшем.
Исходный код проекта (C#, Visual Studio 2010):
mvc3-in-depth-validation-02.zip