Dodawanie walidacji do modelu (C#)

Autor : Rick Anderson

Uwaga

Zaktualizowana wersja tego samouczka jest dostępna tutaj, która używa ASP.NET MVC 5 i Visual Studio 2013. Jest ona bezpieczniejsza, znacznie prostsza do naśladowania i demonstruje więcej funkcji.

Ten samouczek zawiera podstawowe informacje na temat tworzenia aplikacji internetowej MVC ASP.NET przy użyciu programu Microsoft Visual Web Developer 2010 Express z dodatkiem Service Pack 1, który jest bezpłatną wersją programu Microsoft Visual Studio. Przed rozpoczęciem upewnij się, że zostały zainstalowane wymagania wstępne wymienione poniżej. Wszystkie te elementy można zainstalować, klikając następujący link: Instalator platformy sieci Web. Alternatywnie można osobno zainstalować wymagania wstępne, korzystając z następujących linków:

Jeśli używasz programu Visual Studio 2010 zamiast Visual Web Developer 2010, zainstaluj wymagania wstępne, klikając następujący link: Wymagania wstępne programu Visual Studio 2010.

Projekt Visual Web Developer z kodem źródłowym języka C# jest dostępny do dołączenia do tego tematu. Pobierz wersję języka C#. Jeśli wolisz język Visual Basic, przejdź do wersji Visual Basic tego samouczka.

W tej sekcji dodasz logikę walidacji do Movie modelu i upewnisz się, że reguły walidacji są wymuszane za każdym razem, gdy użytkownik spróbuje utworzyć lub edytować film przy użyciu aplikacji.

Utrzymywanie suchej rzeczy

Jedną z podstawowych zasad projektowania ASP.NET MVC jest DRY ("Nie powtarzaj siebie"). ASP.NET MVC zachęca do określenia funkcjonalności lub zachowania tylko raz, a następnie ich odzwierciedlenia wszędzie w aplikacji. Zmniejsza to ilość kodu, który należy napisać i sprawia, że pisanie kodu jest znacznie łatwiejsze do utrzymania.

Obsługa walidacji zapewniana przez ASP.NET MVC i Entity Framework Code First jest doskonałym przykładem zasady DRY w działaniu. Reguły walidacji można deklaratywnie określić w jednym miejscu (w klasie modelu), a następnie te reguły są wymuszane wszędzie w aplikacji.

Przyjrzyjmy się, jak można skorzystać z tej obsługi walidacji w aplikacji filmowej.

Dodawanie reguł walidacji do modelu filmowego

Zaczniesz od dodania logiki walidacji do Movie klasy .

Otwórz plik Movie.cs . Dodaj instrukcję using w górnej części pliku, który odwołuje się do System.ComponentModel.DataAnnotations przestrzeni nazw:

using System.ComponentModel.DataAnnotations;

Przestrzeń nazw jest częścią .NET Framework. Zapewnia wbudowany zestaw atrybutów weryfikacji, które można deklaratywnie stosować do dowolnej klasy lub właściwości.

Teraz zaktualizuj klasę, Movie aby korzystać z wbudowanych Requiredatrybutów , StringLengthi Range walidacji. Użyj następującego kodu jako przykładu miejsca zastosowania atrybutów.

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; }
}

Atrybuty weryfikacji określają zachowanie, do którego mają być wymuszane właściwości modelu. Atrybut Required wskazuje, że właściwość musi mieć wartość. W tym przykładzie film musi mieć wartości właściwości Title, ReleaseDate, Genrei Price , aby być prawidłowe. Atrybut Range ogranicza wartość do określonego zakresu. Atrybut StringLength pozwala ustawić maksymalną długość właściwości ciągu i opcjonalnie jego minimalną długość.

Code First gwarantuje, że reguły weryfikacji określone w klasie modelu są wymuszane przed zapisaniem zmian w bazie danych przez aplikację. Na przykład poniższy kod zgłosi wyjątek po SaveChanges wywołaniu metody, ponieważ brakuje kilku wymaganych Movie wartości właściwości, a cena jest równa zero (która jest wyjątkiem prawidłowego zakresu).

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

Automatyczne wymuszanie reguł weryfikacji przez .NET Framework pomaga zwiększyć niezawodność aplikacji. Gwarantuje to również, że nie można zapomnieć o weryfikacji czegoś i przypadkowo nie zezwalaj na nieprawidłowe dane w bazie danych.

Oto kompletna lista kodu dla zaktualizowanego pliku Movie.cs :

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; }
    }
}

Interfejs użytkownika błędu weryfikacji w ASP.NET MVC

Uruchom ponownie aplikację i przejdź do adresu URL /Movies .

Kliknij link Utwórz film , aby dodać nowy film. Wypełnij formularz kilkoma nieprawidłowymi wartościami, a następnie kliknij przycisk Utwórz .

8_validationErrors

Zwróć uwagę, że formularz automatycznie użył koloru tła do wyróżnienia pól tekstowych zawierających nieprawidłowe dane i emitował odpowiedni komunikat o błędzie weryfikacji obok każdego z nich. Komunikaty o błędach są zgodne z ciągami błędów określonymi podczas dodawania adnotacji do Movie klasy. Błędy są wymuszane zarówno po stronie klienta (przy użyciu języka JavaScript), jak i po stronie serwera (w przypadku wyłączenia języka JavaScript przez użytkownika).

Prawdziwą korzyścią jest to, że nie trzeba było zmieniać pojedynczego wiersza kodu w MoviesController klasie ani w widoku Create.cshtml w celu włączenia tego interfejsu użytkownika weryfikacji. Kontroler i widoki utworzone wcześniej w tym samouczku automatycznie odebrały reguły weryfikacji określone przy użyciu atrybutów w Movie klasie modelu.

Jak występuje walidacja w metodzie Create View i Create Action

Możesz się zastanawiać, w jaki sposób interfejs użytkownika weryfikacji został wygenerowany bez aktualizacji kodu w kontrolerze lub widokach. Następna lista pokazuje, Create jak wyglądają metody w MovieController klasie. Są one niezmienione w sposobie ich tworzenia wcześniej w tym samouczku.

//
// 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);
}

Pierwsza metoda akcji wyświetla początkowy formularz Tworzenia. Drugi obsługuje wpis formularza. Druga Create metoda wywołuje metodę ModelState.IsValid w celu sprawdzenia, czy film ma błędy walidacji. Wywołanie tej metody ocenia wszystkie atrybuty weryfikacji, które zostały zastosowane do obiektu. Jeśli obiekt zawiera błędy sprawdzania poprawności, Create metoda redisplays formularza. Jeśli nie ma żadnych błędów, metoda zapisuje nowy film w bazie danych.

Poniżej znajduje się szablon widoku Create.cshtml utworzony wcześniej w samouczku. Jest ona używana przez metody akcji pokazane powyżej, aby wyświetlić formularz początkowy i ponownie go odtworzyć w przypadku błędu.

@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>

Zwróć uwagę, że kod używa Html.EditorFor pomocnika do wyprowadzania <input> elementu dla każdej Movie właściwości. Obok tego pomocnika jest wywołanie metody pomocniczej Html.ValidationMessageFor . Te dwie metody pomocnicze współdziałają z obiektem modelu przekazywanym przez kontroler do widoku (w tym przypadku obiektem Movie ). Automatycznie wyszukują atrybuty weryfikacji określone w modelu i wyświetlają odpowiednio komunikaty o błędach.

W tym podejściu naprawdę miło jest to, że ani kontroler, ani szablon tworzenia widoku nie wie nic o rzeczywistych regułach walidacji, które są wymuszane, ani o wyświetlanych konkretnych komunikatach o błędach. Reguły walidacji i ciągi błędów są określane tylko w Movie klasie.

Jeśli chcesz później zmienić logikę weryfikacji, możesz to zrobić w dokładnie jednym miejscu. Nie trzeba martwić się o niespójność różnych części aplikacji ze sposobem wymuszania reguł — cała logika walidacji będzie definiowana w jednym miejscu i używana wszędzie. Dzięki temu kod jest bardzo czysty i ułatwia konserwację i rozwijanie. Oznacza to, że będziesz w pełni przestrzegać zasady DRY.

Dodawanie formatowania do modelu filmowego

Otwórz plik Movie.cs . System.ComponentModel.DataAnnotations Przestrzeń nazw udostępnia atrybuty formatowania oprócz wbudowanego zestawu atrybutów weryfikacji. Zastosujesz DisplayFormat atrybut i DataType wartość wyliczenia do daty wydania i pól price. Poniższy kod przedstawia ReleaseDate właściwości i Price z odpowiednim DisplayFormat atrybutem.

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

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

Alternatywnie można jawnie ustawić DataFormatString wartość. Poniższy kod przedstawia właściwość daty wydania z ciągiem formatu daty (a mianowicie "d"). Użyjesz tej opcji, aby określić, że nie chcesz korzystać z godziny w ramach daty wydania.

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

Poniższy kod formatuje właściwość jako walutę Price .

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

Poniżej przedstawiono kompletną Movie klasę.

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; }
}

Uruchom aplikację i przejdź do Movies kontrolera.

8_format_SM

W następnej części serii przejrzymy aplikację i wprowadzimy pewne ulepszenia w automatycznie generowanych Details metodach i Delete .