Część 9, Dodawanie walidacji do aplikacji ASP.NET Core MVCPart 9, add validation to an ASP.NET Core MVC app

Autor: Rick AndersonBy Rick Anderson

W tej sekcji:In this section:

  • Logika walidacji jest dodawana do Movie modelu.Validation logic is added to the Movie model.
  • Upewnij się, że reguły walidacji są wymuszane za każdym razem, gdy użytkownik tworzy lub edytuje film.You ensure that the validation rules are enforced any time a user creates or edits a movie.

Przechowywanie SUCHEj zawartościKeeping things DRY

Jeden z założenia projektu MVC jest suchy ("nie powtarzaj się").One of the design tenets of MVC is DRY ("Don't Repeat Yourself"). ASP.NET Core MVC zachęca do określania funkcjonalności lub zachowania tylko raz, a następnie znajdować się w dowolnym miejscu w aplikacji.ASP.NET Core MVC encourages you to specify functionality or behavior only once, and then have it be reflected everywhere in an app. Pozwala to zmniejszyć ilość kodu, który trzeba napisać, i sprawia, że kod jest mniej podatny na błędy, łatwiejszy do testowania i łatwiejszy w obsłudze.This reduces the amount of code you need to write and makes the code you do write less error prone, easier to test, and easier to maintain.

Obsługa walidacji świadczona przez MVC i Entity Framework Core Code First jest dobrym przykładem zasady SUCHa w działaniu.The validation support provided by MVC and Entity Framework Core Code First is a good example of the DRY principle in action. Można deklaratywnie określić reguły walidacji w jednym miejscu (w klasie modelu), a reguły są wymuszane wszędzie w aplikacji.You can declaratively specify validation rules in one place (in the model class) and the rules are enforced everywhere in the app.

Dodawanie reguł walidacji do modelu filmuAdd validation rules to the movie model

Przestrzeń nazw DataAnnotations zawiera zestaw wbudowanych atrybutów walidacji, które są stosowane deklaratywnie do klasy lub właściwości.The DataAnnotations namespace provides a set of built-in validation attributes that are applied declaratively to a class or property. Adnotacje DataAnnotation zawierają również atrybuty formatowania, takie jak DataType Pomoc dotycząca formatowania i nie zapewniają weryfikacji.DataAnnotations also contains formatting attributes like DataType that help with formatting and don't provide any validation.

Zaktualizuj Movie klasę, aby skorzystać z wbudowanych Required StringLength atrybutów,, RegularExpression i Range walidacji.Update the Movie class to take advantage of the built-in Required, StringLength, RegularExpression, and Range validation attributes.

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

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string Title { get; set; }

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string Rating { get; set; }
}

Atrybuty walidacji określają zachowanie, które chcesz wymusić na właściwościach modelu, do których są stosowane:The validation attributes specify behavior that you want to enforce on the model properties they're applied to:

  • RequiredAtrybuty i MinimumLength wskazują, że właściwość musi mieć wartość, ale nic nie zapobiega wprowadzaniu przez użytkownika odstępu w celu zaspokojenia tej walidacji.The Required and MinimumLength attributes indicate that a property must have a value; but nothing prevents a user from entering white space to satisfy this validation.

  • Ten RegularExpression atrybut służy do ograniczania, jakie znaki mogą być wprowadzane.The RegularExpression attribute is used to limit what characters can be input. W poprzednim kodzie "gatunek":In the preceding code, "Genre":

    • Należy używać tylko liter.Must only use letters.
    • Pierwsza litera musi być wielką literą.The first letter is required to be uppercase. Odstępy, cyfry i znaki specjalne są niedozwolone.White space, numbers, and special characters are not allowed.
  • RegularExpression"Ocena":The RegularExpression "Rating":

    • Wymaga, aby pierwszy znak był wielką literą.Requires that the first character be an uppercase letter.
    • Zezwala na znaki specjalne i cyfry w kolejnych odstępach.Allows special characters and numbers in subsequent spaces. "PG-13" jest prawidłowy dla oceny, ale kończy się niepowodzeniem dla "gatunku"."PG-13" is valid for a rating, but fails for a "Genre".
  • Atrybut Range ogranicza wartość do określonego zakresu.The Range attribute constrains a value to within a specified range.

  • Ten StringLength atrybut pozwala ustawić maksymalną długość właściwości ciągu i opcjonalnie jej długość minimalną.The StringLength attribute lets you set the maximum length of a string property, and optionally its minimum length.

  • Typy wartości (takie jak decimal ,,, int float DateTime ) są z założenia wymagane i nie wymagają [Required] atrybutu.Value types (such as decimal, int, float, DateTime) are inherently required and don't need the [Required] attribute.

Automatyczne Wymuszanie reguł sprawdzania poprawności przez ASP.NET Core pomaga zwiększyć niezawodność aplikacji.Having validation rules automatically enforced by ASP.NET Core helps make your app more robust. Gwarantuje to również, że nie można zapomnieć, aby zweryfikować coś i przypadkowo umożliwić niewłaściwe dane w bazie danych.It also ensures that you can't forget to validate something and inadvertently let bad data into the database.

Interfejs użytkownika błędu walidacjiValidation Error UI

Uruchom aplikację i przejdź do kontrolera filmów.Run the app and navigate to the Movies controller.

Naciśnij link Utwórz nowy , aby dodać nowy film.Tap the Create New link to add a new movie. Wypełnij formularz nieprawidłowymi wartościami.Fill out the form with some invalid values. Gdy tylko Walidacja po stronie klienta jQuery wykryje błąd, zostanie wyświetlony komunikat o błędzie.As soon as jQuery client side validation detects the error, it displays an error message.

Formularz wyświetlania filmu z wieloma błędami walidacji po stronie klienta jQuery

Uwaga

Może nie być możliwe wprowadzanie przecinków dziesiętnych w polach dziesiętnych.You may not be able to enter decimal commas in decimal fields. Aby zapewnić obsługę walidacji jQuery dla ustawień regionalnych innych niż angielskie, które używają przecinka (",") dla przecinka dziesiętnego i nieUS-Englishych formatów daty, należy wykonać kroki w celu globalizacji aplikacji.To support jQuery validation for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. Aby uzyskać instrukcje dotyczące dodawania przecinków dziesiętnych, Zobacz ten problem w usłudze GitHub 4076 .See this GitHub issue 4076 for instructions on adding decimal comma.

Zwróć uwagę, jak formularz automatycznie renderuje odpowiedni komunikat o błędzie walidacji w każdym polu zawierającym nieprawidłową wartość.Notice how the form has automatically rendered an appropriate validation error message in each field containing an invalid value. Błędy są wymuszane po stronie klienta (przy użyciu języków JavaScript i jQuery) i po stronie serwera (w przypadku, gdy użytkownik ma wyłączony kod JavaScript).The errors are enforced both client-side (using JavaScript and jQuery) and server-side (in case a user has JavaScript disabled).

Znacząca korzyść polega na tym, że nie trzeba zmieniać pojedynczego wiersza kodu w MoviesController klasie lub w widoku Create. cshtml , aby włączyć ten interfejs użytkownika weryfikacji.A significant 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. Kontroler i widoki utworzone wcześniej w tym samouczku automatycznie pobierają reguły sprawdzania poprawności określone przy użyciu atrybutów walidacji we właściwościach Movie klasy modelu.The controller and views you created earlier in this tutorial automatically picked up the validation rules that you specified by using validation attributes on the properties of the Movie model class. Sprawdzanie poprawności testu przy użyciu Edit metody akcji i zastosowanie tej samej walidacji.Test validation using the Edit action method, and the same validation is applied.

Dane formularza nie są wysyłane do serwera, dopóki nie zostaną wykryte błędy weryfikacji po stronie klienta.The form data isn't sent to the server until there are no client side validation errors. Można to sprawdzić, umieszczając punkt przerwania w HTTP Post metodzie przy użyciu Narzędzia programu Fiddler lub narzędzi programistycznych F12.You can verify this by putting a break point in the HTTP Post method, by using the Fiddler tool , or the F12 Developer tools.

Jak działa WalidacjaHow validation works

Możesz zastanawiać się, jak został wygenerowany interfejs użytkownika weryfikacji bez aktualizacji kodu w kontrolerze lub widokach.You might wonder how the validation UI was generated without any updates to the code in the controller or views. Poniższy kod przedstawia dwie Create metody.The following code shows the two Create methods.

// GET: Movies/Create
public IActionResult Create()
{
    return View();
}

// POST: Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
    [Bind("ID,Title,ReleaseDate,Genre,Price, Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction("Index");
    }
    return View(movie);
}

Pierwsza metoda akcji (HTTP GET) Create zawiera początkowy formularz tworzenia.The first (HTTP GET) Create action method displays the initial Create form. Druga wersja ( [HttpPost] ) obsługuje wpis w formularzu.The second ([HttpPost]) version handles the form post. Druga Create Metoda ( [HttpPost] wersja) wywołania, ModelState.IsValid Aby sprawdzić, czy film ma jakiekolwiek błędy walidacji.The second Create method (The [HttpPost] version) calls ModelState.IsValid to check whether the movie has any validation errors. Wywołanie tej metody szacuje wszystkie atrybuty walidacji, które zostały zastosowane do obiektu.Calling this method evaluates any validation attributes that have been applied to the object. Jeśli obiekt ma błędy walidacji, Create Metoda ponowna wyświetli formularz.If the object has validation errors, the Create method re-displays the form. Jeśli nie ma żadnych błędów, Metoda zapisuje nowy film w bazie danych.If there are no errors, the method saves the new movie in the database. W naszym przykładzie filmu nie jest on ogłaszany na serwerze, gdy na stronie klienta wykryto błędy walidacji. Druga Create Metoda nie jest nigdy wywoływana, gdy występują błędy walidacji po stronie klienta.In our movie example, the form isn't posted to the server when there are validation errors detected on the client side; the second Create method is never called when there are client side validation errors. W przypadku wyłączenia języka JavaScript w przeglądarce sprawdzanie poprawności klienta jest wyłączone i można przetestować metodę POST protokołu HTTP w celu Create ModelState.IsValid wykrycia błędów walidacji.If you disable JavaScript in your browser, client validation is disabled and you can test the HTTP POST Create method ModelState.IsValid detecting any validation errors.

Można ustawić punkt przerwania w [HttpPost] Create metodzie i sprawdzić, czy metoda nie jest nigdy wywoływana, podczas walidacji po stronie klienta nie będą przesyłane dane formularza po wykryciu błędów walidacji.You can set a break point in the [HttpPost] Create method and verify the method is never called, client side validation won't submit the form data when validation errors are detected. Jeśli wyłączysz JavaScript w przeglądarce, a następnie prześlesz formularz z błędami, zostanie osiągnięty punkt przerwania.If you disable JavaScript in your browser, then submit the form with errors, the break point will be hit. Nadal będziesz mieć pełną weryfikację bez języka JavaScript.You still get full validation without JavaScript.

Na poniższej ilustracji przedstawiono sposób wyłączania języka JavaScript w przeglądarce Firefox.The following image shows how to disable JavaScript in the Firefox browser.

Firefox: na karcie zawartość w obszarze Opcje usuń zaznaczenie pola wyboru Włącz język JavaScript.

Na poniższej ilustracji przedstawiono sposób wyłączania języka JavaScript w przeglądarce Chrome.The following image shows how to disable JavaScript in the Chrome browser.

Google Chrome: w sekcji JavaScript ustawień zawartości wybierz opcję nie Zezwalaj na uruchamianie skryptów JavaScript przez żadną lokację.

Po wyłączeniu języka JavaScript Opublikuj nieprawidłowe dane i przechodzenie przez debuger.After you disable JavaScript, post invalid data and step through the debugger.

Podczas debugowania wpisu nieprawidłowych danych funkcja IntelliSense w ModelState. IsValid pokazuje wartość false.

Część szablonu widoku Create. cshtml jest pokazana w następującej postaci:The portion of the Create.cshtml view template is shown in the following markup:


<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>           
       
        @*Markup removed for brevity.*@

Poprzedzające znaczniki są używane przez metody akcji, aby wyświetlić początkowy formularz i ponownie wyświetlić go w przypadku błędu.The preceding markup is used by the action methods to display the initial form and to redisplay it in the event of an error.

Pomocnik tagu wejściowego używa atrybutów DataAnnotations i tworzy atrybuty HTML, które są zbędne do walidacji jQuery po stronie klienta.The Input Tag Helper uses the DataAnnotations attributes and produces HTML attributes needed for jQuery Validation on the client side. Pomocnik tagów walidacji wyświetla błędy walidacji.The Validation Tag Helper displays validation errors. Aby uzyskać więcej informacji, zobacz Walidacja .See Validation for more information.

W rzeczywistości to podejście jest takie, że ani kontroler, ani Create szablon widoku nie wie o faktycznych regułach walidacji lub o określonych komunikatach o błędach.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. Reguły walidacji i ciągi błędów są określone tylko w Movie klasie.The validation rules and the error strings are specified only in the Movie class. Te same reguły sprawdzania poprawności są automatycznie stosowane do Edit widoku i wszystkich innych szablonów widoków, które można utworzyć, edytując model.These same validation rules are automatically applied to the Edit view and any other views templates you might create that edit your model.

W przypadku konieczności zmiany logiki walidacji można to zrobić w dokładnie jednym miejscu przez dodanie atrybutów sprawdzania poprawności do modelu (w tym przykładzie Movie Klasa).When you need to change validation logic, you can do so in exactly one place by adding validation attributes to the model (in this example, the Movie class). Nie trzeba martwić się o różne części aplikacji, które nie są zgodne z zasadami, w których są wymuszane — Cała logika walidacji zostanie zdefiniowana w jednym miejscu i użyta wszędzie.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. Dzięki temu kod jest bardzo czysty i ułatwia utrzymanie i rozwój.This keeps the code very clean, and makes it easy to maintain and evolve. Oznacza to, że będziesz w pełni przestrzegać SUCHEj zasady.And it means that you'll be fully honoring the DRY principle.

Używanie atrybutów DataTypeUsing DataType Attributes

Otwórz plik Movie.cs i zapoznaj się z Movie klasą.Open the Movie.cs file and examine the Movie class. System.ComponentModel.DataAnnotationsPrzestrzeń nazw zawiera atrybuty formatowania oprócz wbudowanego zestawu atrybutów walidacji.The System.ComponentModel.DataAnnotations namespace provides formatting attributes in addition to the built-in set of validation attributes. Wartość wyliczenia została już zastosowana DataType do daty wydania i do pól cen.We've already applied a DataType enumeration value to the release date and to the price fields. Poniższy kod pokazuje ReleaseDate Price właściwości i z odpowiednim DataType atrybutem.The following code shows the ReleaseDate and Price properties with the appropriate DataType attribute.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

DataTypeAtrybuty zawierają tylko wskazówki dla aparatu widoku do formatowania danych (i udostępniają elementy/atrybuty, takie jak <a> adresy URL i <a href="mailto:EmailAddress.com"> wiadomości e-mail.The DataType attributes only provide hints for the view engine to format the data (and supplies elements/attributes such as <a> for URL's and <a href="mailto:EmailAddress.com"> for email. Możesz użyć atrybutu, RegularExpression Aby sprawdzić poprawność formatu danych.You can use the RegularExpression attribute to validate the format of the data. Ten DataType atrybut służy do określania typu danych, który jest bardziej szczegółowy niż typ wewnętrzny bazy danych, nie są atrybutami walidacji.The DataType attribute is used to specify a data type that's more specific than the database intrinsic type, they're not validation attributes. W tym przypadku chcemy tylko śledzić datę, a nie godzinę.In this case we only want to keep track of the date, not the time. DataTypeWyliczenie zawiera wiele typów danych, takich jak data, godzina, numer telefonu, waluta, EmailAddress i inne.The DataType Enumeration provides for many data types, such as Date, Time, PhoneNumber, Currency, EmailAddress and more. Ten DataType atrybut może również umożliwić aplikacji automatyczne udostępnianie funkcji specyficznych dla typu.The DataType attribute can also enable the application to automatically provide type-specific features. Na przykład mailto: można utworzyć łącze dla i dla programu DataType.EmailAddress DataType.Date w przeglądarkach, które obsługują HTML5, można podać selektor daty.For example, a mailto: link can be created for DataType.EmailAddress, and a date selector can be provided for DataType.Date in browsers that support HTML5. DataTypeAtrybuty emitują HTML 5 data- (wymawiane kreski danych), które mogą zrozumieć przeglądarki HTML 5.The DataType attributes emit HTML 5 data- (pronounced data dash) attributes that HTML 5 browsers can understand. DataTypeAtrybuty nie zapewniają żadnej weryfikacji.The DataType attributes do not provide any validation.

DataType.Date nie określa formatu wyświetlanej daty.DataType.Date doesn't specify the format of the date that's displayed. Domyślnie pole dane jest wyświetlane zgodnie z domyślnymi formatami opartymi na serwerze CultureInfo .By default, the data field is displayed according to the default formats based on the server's CultureInfo.

Ten DisplayFormat atrybut służy do jawnego określenia formatu daty:The DisplayFormat attribute is used to explicitly specify the date format:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

ApplyFormatInEditModeUstawienie określa, że formatowanie powinno być również stosowane, gdy wartość jest wyświetlana w polu tekstowym do edycji.The ApplyFormatInEditMode setting specifies that the formatting should also be applied when the value is displayed in a text box for editing. (Możesz nie chcieć, aby w przypadku niektórych pól — na przykład w przypadku wartości walutowych, prawdopodobnie nie chcesz, aby symbol waluty był widoczny w polu tekstowym do edycji).(You might not want that for some fields — for example, for currency values, you probably don't want the currency symbol in the text box for editing.)

Możesz użyć DisplayFormat atrybutu przez siebie, ale zazwyczaj dobrym pomysłem jest użycie DataType atrybutu.You can use the DisplayFormat attribute by itself, but it's generally a good idea to use the DataType attribute. Ten DataType atrybut przekazuje semantykę danych w przeciwieństwie do sposobu renderowania na ekranie i zapewnia następujące korzyści, których nie można uzyskać za pomocą DisplayFormat:The DataType attribute conveys the semantics of the data as opposed to how to render it on a screen, and provides the following benefits that you don't get with DisplayFormat:

  • Przeglądarka może włączać funkcje HTML5 (na przykład w celu wyświetlania kontrolki kalendarza, symbolu waluty właściwej dla ustawień regionalnych, linków e-mail itp.).The browser can enable HTML5 features (for example to show a calendar control, the locale-appropriate currency symbol, email links, etc.)

  • Domyślnie przeglądarka będzie renderować dane przy użyciu poprawnego formatu na podstawie ustawień regionalnych.By default, the browser will render data using the correct format based on your locale.

  • Ten DataType atrybut umożliwia wybranie odpowiedniego szablonu pola do renderowania danych DisplayFormat przez MVC. (Jeśli używane przez siebie korzysta z szablonu ciągu).The DataType attribute can enable MVC to choose the right field template to render the data (the DisplayFormat if used by itself uses the string template).

Uwaga

Walidacja jQuery nie działa z Range atrybutem i DateTime .jQuery validation doesn't work with the Range attribute and DateTime. Na przykład poniższy kod zawsze będzie wyświetlał błąd walidacji po stronie klienta, nawet wtedy, gdy data jest w określonym zakresie:For example, the following code will always display a client side validation error, even when the date is in the specified range:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Należy wyłączyć sprawdzanie poprawności daty jQuery, aby użyć Range atrybutu z DateTime .You will need to disable jQuery date validation to use the Range attribute with DateTime. Ogólnie rzecz biorąc, nie jest dobrym sposobem kompilowania dat stałych w modelach, dlatego przy użyciu Range atrybutu i DateTime nie jest to odradzane.It's generally not a good practice to compile hard dates in your models, so using the Range attribute and DateTime is discouraged.

Poniższy kod ilustruje łączenie atrybutów w jednym wierszu:The following code shows combining attributes on one line:

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

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z]*$"), Required, StringLength(30)]
    public string Genre { get; set; }

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; }
}

W następnej części serii przeglądamy aplikację i wprowadzamy pewne ulepszenia dla automatycznie generowanych Details i Delete metod.In the next part of the series, we review the app and make some improvements to the automatically generated Details and Delete methods.

Dodatkowe zasobyAdditional resources