Добавление проверки в модель (C#)Adding Validation to the Model (C#)

по Рик Андерсон (by Rick Anderson

Note

Обновленная версия этого учебника доступна здесь , в которой используется ASP.NET MVC 5 и Visual Studio 2013.An updated version of this tutorial is available here that uses ASP.NET MVC 5 and Visual Studio 2013. Он более безопасен, гораздо проще следовать и демонстрирует дополнительные функции.It's more secure, much simpler to follow and demonstrates more features.

В этом учебнике вы узнаете об основах создания веб-приложения ASP.NET MVC с помощью Microsoft Visual Web Developer 2010 Express с пакетом обновления 1 (SP1), который является бесплатной версией Microsoft Visual Studio.This tutorial will teach you the basics of building an ASP.NET MVC Web application using Microsoft Visual Web Developer 2010 Express Service Pack 1, which is a free version of Microsoft Visual Studio. Прежде чем начать, убедитесь, что установлены предварительные требования, перечисленные ниже.Before you start, make sure you've installed the prerequisites listed below. Чтобы установить все эти компоненты, щелкните следующую ссылку: установщик веб-платформы.You can install all of them by clicking the following link: Web Platform Installer. Кроме того, вы можете отдельно установить необходимые компоненты, используя следующие ссылки:Alternatively, you can individually install the prerequisites using the following links:

Если вы используете Visual Studio 2010 вместо Visual Web Developer 2010, установите необходимые компоненты, щелкнув следующую ссылку: Предварительные требования для Visual studio 2010.If you're using Visual Studio 2010 instead of Visual Web Developer 2010, install the prerequisites by clicking the following link: Visual Studio 2010 prerequisites.

Для этого раздела доступен проект Visual C# Web Developer с исходным кодом.A Visual Web Developer project with C# source code is available to accompany this topic. Скачайте C# версию.Download the C# version. Если вы предпочитаете Visual Basic, переключитесь на Visual Basic версию этого учебника.If you prefer Visual Basic, switch to the Visual Basic version of this tutorial.

В этом разделе вы добавите логику проверки к модели Movie, и вы убедитесь, что правила проверки применяются каждый раз, когда пользователь попытается создать или изменить фильм с помощью приложения.In this section you'll add validation logic to the Movie model, and you'll ensure that the validation rules are enforced any time a user attempts to create or edit a movie using the application.

Поддержание СУХИх вещейKeeping Things DRY

Один из основных принципов проектирования ASP.NET MVC — сухой ("принцип"Не повторяйся"").One of the core design tenets of ASP.NET MVC is DRY ("Don't Repeat Yourself"). ASP.NET MVC позволяет указать функциональные возможности или поведение только один раз, после чего они будут отражены в любом приложении.ASP.NET MVC encourages you to specify functionality or behavior only once, and then have it be reflected everywhere in an application. Это сокращает объем кода, который необходимо написать, и делает написанный код гораздо проще в обслуживании.This reduces the amount of code you need to write and makes the code you do write much easier to maintain.

Поддержка проверки, предоставляемая ASP.NET MVC и Entity Framework Code First, является хорошим примером принципа сухой в действии.The validation support provided by ASP.NET MVC and Entity Framework Code First is a great example of the DRY principle in action. Правила проверки можно декларативно задавать в одном месте (в классе Model), а затем эти правила применяются везде в приложении.You can declaratively specify validation rules in one place (in the model class) and then those rules are enforced everywhere in the application.

Рассмотрим, как можно воспользоваться преимуществами этой поддержки проверки в приложении Movie.Let's look at how you can take advantage of this validation support in the movie application.

Добавление правил проверки к модели фильмовAdding Validation Rules to the Movie Model

Начнем с добавления логики проверки к классу Movie.You'll begin by adding some validation logic to the Movie class.

Откройте файл Movie.cs.Open the Movie.cs file. Добавьте в начало файла инструкцию using, которая ссылается на пространство имен System.ComponentModel.DataAnnotations :Add a using statement at the top of the file that references the System.ComponentModel.DataAnnotations namespace:

using System.ComponentModel.DataAnnotations;

Пространство имен является частью .NET Framework.The namespace is part of the .NET Framework. Он предоставляет встроенный набор атрибутов проверки, которые можно декларативно применять к любому классу или свойству.It provides a built-in set of validation attributes that you can apply declaratively to any class or property.

Теперь обновите класс Movie, чтобы воспользоваться преимуществами встроенных Required, StringLengthи Range атрибутов проверки.Now update the Movie class to take advantage of the built-in Required, StringLength, and Range validation attributes. Используйте следующий код в качестве примера того, где применять атрибуты.Use the following code as an example of where to apply the attributes.

public class Movie
{
    public int ID { get; set; }

    [Required(ErrorMessage = "Title is required")]
    public string Title { get; set; }

    [Required(ErrorMessage = "Date is required")]
    public DateTime ReleaseDate { get; set; }

    [Required(ErrorMessage = "Genre must be specified")]
    public string Genre { get; set; }

    [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")]
    public decimal Price { get; set; }

    [StringLength(5)]
    public string Rating { get; set; }
}

Атрибуты проверки определяют поведение для свойств модели, к которым они применяются.The validation attributes specify behavior that you want to enforce on the model properties they are applied to. Атрибут Required указывает, что свойство должно иметь значение. в этом примере фильм должен иметь значения для свойств Title, ReleaseDate, Genreи Price, чтобы быть допустимыми.The Required attribute indicates that a property must have a value; in this sample, a movie has to have values for the Title, ReleaseDate, Genre, and Price properties in order to be valid. Атрибут Range ограничивает диапазон значений.The Range attribute constrains a value to within a specified range. Атрибут StringLength позволяет задать максимальную и при необходимости минимальную длину строкового свойства.The StringLength attribute lets you set the maximum length of a string property, and optionally its minimum length.

Code First гарантирует, что правила проверки, указанные в классе модели, будут применены, прежде чем приложение сохранит изменения в базе данных.Code First ensures that the validation rules you specify on a model class are enforced before the application saves changes in the database. Например, приведенный ниже код вызывает исключение при вызове метода SaveChanges, так как отсутствуют несколько обязательных Movie значений свойств и цена равна нулю (за пределами допустимого диапазона).For example, the code below will throw an exception when the SaveChanges method is called, because several required Movie property values are missing and the price is zero (which is out of the valid range).

MovieDBContext db = new MovieDBContext();

Movie movie = new Movie();
movie.Title = "Gone with the Wind";
movie.Price = 0.0M;

db.Movies.Add(movie);
db.SaveChanges();        // <= Will throw validation exception

Если правила проверки автоматически принудительно применяются .NET Framework помогает сделать приложение более надежным.Having validation rules automatically enforced by the .NET Framework helps make your application more robust. Это также гарантирует, что в любом случае будут выполнены все проверки и в базе данных не будут случайно оставлены поврежденные данные.It also ensures that you can't forget to validate something and inadvertently let bad data into the database.

Ниже приведен полный листинг кода для обновленного файла Movie.CS :Here's a complete code listing for the updated Movie.cs file:

using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [Required(ErrorMessage = "Title is required")]
        public string Title { get; set; }

        public DateTime ReleaseDate { get; set; }

        [Required(ErrorMessage = "Genre must be specified")]
        public string Genre { get; set; }

        [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")]
        public decimal Price { get; set; }

        [StringLength(5)]
        public string Rating { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}

Пользовательский интерфейс ошибки проверки в ASP.NET MVCValidation Error UI in ASP.NET MVC

Повторно запустите приложение и перейдите по URL-адресу /Movies .Re-run the application and navigate to the /Movies URL.

Щелкните ссылку создать фильм , чтобы добавить новый фильм.Click the Create Movie link to add a new movie. Заполните форму недопустимыми значениями и нажмите кнопку " создать ".Fill out the form with some invalid values and then click the Create button.

8_validationErrors8_validationErrors

Обратите внимание, что форма автоматически использовала цвет фона для выделения текстовых полей, содержащих недопустимые данные, и выдает соответствующее сообщение об ошибке проверки рядом с каждым из них.Notice how the form has automatically used a background color to highlight the text boxes that contain invalid data and has emitted an appropriate validation error message next to each one. Сообщения об ошибках соответствуют строкам ошибок, указанным при создании заметки к Movie классу.The error messages match the error strings you specified when you annotated the Movie class. Эти ошибки применяются как на стороне клиента (с помощью JavaScript), так и на стороне сервера (если пользователь отключил JavaScript).The errors are enforced both client-side (using JavaScript) and server-side (in case a user has JavaScript disabled).

Настоящим преимуществом является то, что вам не пришлось изменять одну строку кода в классе MoviesController или в представлении Create. cshtml , чтобы включить этот пользовательский интерфейс проверки.A real benefit is that you didn't need to change a single line of code in the MoviesController class or in the Create.cshtml view in order to enable this validation UI. Контроллер и представления, созданные ранее в этом учебнике, автоматически задают правила проверки, заданные с помощью атрибутов класса модели Movie.The controller and views you created earlier in this tutorial automatically picked up the validation rules that you specified using attributes on the Movie model class.

Как выполняется проверка в методе создания представления и создания действияHow Validation Occurs in the Create View and Create Action Method

Вам может быть интересно, как пользовательский интерфейс проверки создается без обновления кода контроллера или представлений.You might wonder how the validation UI was generated without any updates to the code in the controller or views. В следующем листинге показано, как выглядят методы Create в классе MovieController.The next listing shows what the Create methods in the MovieController class look like. Они не изменяются из того, как вы создали их ранее в этом руководстве.They're unchanged from how you created them earlier in this tutorial.

//
// GET: /Movies/Create

public ActionResult Create()
{
    return View();
}

//
// POST: /Movies/Create

[HttpPost]
public ActionResult Create(Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Movies.Add(movie);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(movie);
}

Первый метод действия отображает начальную форму создания.The first action method displays the initial Create form. Второй обрабатывает форму Post.The second handles the form post. Второй метод Create вызывает ModelState.IsValid, чтобы проверить, имеются ли в фильме ошибки проверки.The second Create method calls ModelState.IsValid to check whether the movie has any validation errors. При вызове этого метода оцениваются все атрибуты проверки, которые были применены к объекту.Calling this method evaluates any validation attributes that have been applied to the object. Если объект содержит ошибки проверки, метод Create повторно отображает форму.If the object has validation errors, the Create method redisplays the form. Если ошибок нет, метод сохраняет новый фильм в базе данных.If there are no errors, the method saves the new movie in the database.

Ниже приведен шаблон представления Create. cshtml , сформированный ранее в этом руководстве.Below is the Create.cshtml view template that you scaffolded earlier in the tutorial. Он используется в показанных выше методах действия для отображения исходной формы и повторного вывода формы в случае ошибки.It's used by the action methods shown above both to display the initial form and to redisplay it in the event of an error.

@model MvcMovie.Models.Movie
@{
    ViewBag.Title = "Create";
}
<h2>
    Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Movie</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.ReleaseDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ReleaseDate)
            @Html.ValidationMessageFor(model => model.ReleaseDate)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Genre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Genre)
            @Html.ValidationMessageFor(model => model.Genre)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Price)
            @Html.ValidationMessageFor(model => model.Price)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Rating)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Rating)
            @Html.ValidationMessageFor(model => model.Rating)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Обратите внимание, что в коде используется вспомогательный метод Html.EditorFor для вывода элемента <input> для каждого свойства Movie.Notice how the code uses an Html.EditorFor helper to output the <input> element for each Movie property. Рядом с этим вспомогательным модулем вызывается вспомогательный метод Html.ValidationMessageFor.Next to this helper is a call to the Html.ValidationMessageFor helper method. Эти два вспомогательных метода работают с объектом модели, который передается контроллером в представление (в данном случае это объект Movie).These two helper methods work with the model object that's passed by the controller to the view (in this case, a Movie object). Они автоматически ищут атрибуты проверки, указанные в модели, и отображают сообщения об ошибках соответствующим образом.They automatically look for validation attributes specified on the model and display error messages as appropriate.

Все, что хорошо замечательно в этом подходе, заключается в том, что ни контроллер, ни шаблон создания представления не знают о фактических правилах проверки, которые применяются, или о конкретных сообщениях об ошибках.What's really nice about this approach is that neither the controller nor the Create view template knows anything about the actual validation rules being enforced or about the specific error messages displayed. Правила проверки и строки ошибок указываются только в классе Movie.The validation rules and the error strings are specified only in the Movie class.

Если вы хотите изменить логику проверки позже, это можно сделать в одном месте.If you want to change the validation logic later, you can do so in exactly one place. Вам не придется беспокоиться о несогласованности применения правил в различных частях приложения, поскольку вся логика проверки будет определена в одном месте и начнет применяться по всему приложению.You won't have to worry about different parts of the application being inconsistent with how the rules are enforced — all validation logic will be defined in one place and used everywhere. Это позволяет максимально оптимизировать код и обеспечить удобство его совершенствования и поддержки.This keeps the code very clean, and makes it easy to maintain and evolve. Кроме того, таким образом вы будете полностью соблюдать требования принципа "Не повторяйся".And it means that you'll be fully honoring the DRY principle.

Добавление форматирования в модель фильмовAdding Formatting to the Movie Model

Откройте файл Movie.cs.Open the Movie.cs file. Пространство имен System.ComponentModel.DataAnnotations предоставляет атрибуты форматирования в дополнение к встроенному набору атрибутов проверки.The System.ComponentModel.DataAnnotations namespace provides formatting attributes in addition to the built-in set of validation attributes. Вы примените атрибут DisplayFormat и значение перечисления DataType к дате выпуска и к полям цены.You'll apply the DisplayFormat attribute and a DataType enumeration value to the release date and to the price fields. В следующем коде показаны свойства ReleaseDate и Price с соответствующим атрибутом DisplayFormat .The following code shows the ReleaseDate and Price properties with the appropriate DisplayFormat attribute.

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

[DataType(DataType.Currency)] 
public decimal Price { get; set; }

Кроме того, можно явно задать значение DataFormatString .Alternatively, you could explicitly set a DataFormatString value. В следующем коде показано свойство Дата выпуска со строкой формата даты (а именно, "d").The following code shows the release date property with a date format string (namely, "d"). Этот параметр используется для указания, что вы не хотите использовать время в качестве части даты выпуска.You'd use this to specify that you don't want to time as part of the release date.

[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime ReleaseDate { get; set; }

Следующий код форматирует свойство Price как денежное.The following code formats the Price property as currency.

[DisplayFormat(DataFormatString = "{0:c}")]
public decimal Price { get; set; }

Ниже приведен полный класс Movie.The complete Movie class is shown below.

public class Movie
{
    public int ID { get; set; }

    [Required(ErrorMessage = "Title is required")]
    public string Title { get; set; }

    [DisplayFormat(DataFormatString = "{0:d}")]
    public DateTime ReleaseDate { get; set; }

    [Required(ErrorMessage = "Genre must be specified")]
    public string Genre { get; set; }

    [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")]
    [DisplayFormat(DataFormatString = "{0:c}")]
    public decimal Price { get; set; }

    [StringLength(5)]
    public string Rating { get; set; }
}

Запустите приложение и перейдите к контроллеру Movies.Run the application and browse to the Movies controller.

8_format_SM

В следующей части этой серии мы рассмотрим приложение и внесем ряд изменений в автоматически создаваемые методы Details и Delete.In the next part of the series, we'll review the application and make some improvements to the automatically generated Details and Delete methods.