Walidacja modelu w ASP.NET Core MVC i Razor stronachModel validation in ASP.NET Core MVC and Razor Pages

Autor Kirka LarkinBy Kirk Larkin

W tym artykule wyjaśniono, jak sprawdzić poprawność danych wprowadzonych przez użytkownika w aplikacji ASP.NET Core MVC lub Razor Pages.This article explains how to validate user input in an ASP.NET Core MVC or Razor Pages app.

Wyświetlanie lub Pobieranie przykładowego kodu (jak pobrać).View or download sample code (how to download).

Stan modeluModel state

Stan modelu reprezentuje błędy pochodzące z dwóch podsystemów: powiązanie modelu i walidacja modelu.Model state represents errors that come from two subsystems: model binding and model validation. Błędy, które pochodzą z powiązania modelu , są zwykle Błędy konwersji danych.Errors that originate from model binding are generally data conversion errors. Na przykład znak "x" jest wprowadzany w polu liczby całkowitej.For example, an "x" is entered in an integer field. Walidacja modelu odbywa się po powiązaniu modelu i zgłasza błędy, gdy dane nie są zgodne z regułami biznesowymi.Model validation occurs after model binding and reports errors where data doesn't conform to business rules. Na przykład wartość 0 jest wprowadzana w polu, które oczekuje klasyfikacji z przedziału od 1 do 5.For example, a 0 is entered in a field that expects a rating between 1 and 5.

Powiązanie modelu i walidacja modelu są wykonywane przed wykonaniem akcji kontrolera lub Razor metody obsługi stron.Both model binding and model validation occur before the execution of a controller action or a Razor Pages handler method. W przypadku aplikacji sieci Web jest odpowiedzialna za jej sprawdzenie ModelState.IsValid i reagowanie.For web apps, it's the app's responsibility to inspect ModelState.IsValid and react appropriately. Aplikacja internetowa zazwyczaj ponownie wyświetla stronę z komunikatem o błędzie:Web apps typically redisplay the page with an error message:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movies.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Kontrolery interfejsu API sieci Web nie muszą sprawdzać ModelState.IsValid , czy mają [ApiController] atrybut.Web API controllers don't have to check ModelState.IsValid if they have the [ApiController] attribute. W takim przypadku automatyczna odpowiedź HTTP 400 zawierająca szczegóły błędu jest zwracana, gdy stan modelu jest nieprawidłowy.In that case, an automatic HTTP 400 response containing error details is returned when model state is invalid. Aby uzyskać więcej informacji, zobacz Automatyczne HTTP 400 odpowiedzi.For more information, see Automatic HTTP 400 responses.

Uruchom ponownie weryfikacjęRerun validation

Walidacja jest automatyczna, ale warto powtórzyć ją ręcznie.Validation is automatic, but you might want to repeat it manually. Na przykład można obliczyć wartość właściwości i chcieć ponownie uruchomić weryfikację po ustawieniu właściwości na wartość obliczaną.For example, you might compute a value for a property and want to rerun validation after setting the property to the computed value. Aby ponownie uruchomić weryfikację, wywołaj TryValidateModel metodę, jak pokazano poniżej:To rerun validation, call the TryValidateModel method, as shown here:

Movie.ReleaseDate = modifiedReleaseDate;

if (!TryValidateModel(Movie, nameof(Movie)))
{
    return Page();
}

_context.Movies.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");

Atrybuty walidacjiValidation attributes

Atrybuty walidacji umożliwiają określanie reguł walidacji dla właściwości modelu.Validation attributes let you specify validation rules for model properties. W poniższym przykładzie z przykładowej aplikacji przedstawiono klasę modelu, która ma adnotację z atrybutami walidacji.The following example from the sample app shows a model class that is annotated with validation attributes. Ten [ClassicMovie] atrybut jest niestandardowym atrybutem walidacji, a inne są wbudowane.The [ClassicMovie] attribute is a custom validation attribute and the others are built-in. Niepokazywany [ClassicMovieWithClientValidator] .Not shown is [ClassicMovieWithClientValidator]. [ClassicMovieWithClientValidator] pokazuje alternatywny sposób implementacji atrybutu niestandardowego.[ClassicMovieWithClientValidator] shows an alternative way to implement a custom attribute.

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

    [Required]
    [StringLength(100)]
    public string Title { get; set; }

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

    [Required]
    [StringLength(1000)]
    public string Description { get; set; }

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }
}

Atrybuty wbudowaneBuilt-in attributes

Poniżej przedstawiono niektóre wbudowane atrybuty walidacji:Here are some of the built-in validation attributes:

  • [CreditCard]: Sprawdza, czy właściwość ma format karty kredytowej.[CreditCard]: Validates that the property has a credit card format. Wymaga zastosowania dodatkowych metod walidacji jQuery.Requires jQuery Validation Additional Methods.
  • [Compare]: Sprawdza, czy dwie właściwości w modelu pasują do siebie.[Compare]: Validates that two properties in a model match.
  • [EmailAddress]: Sprawdza, czy właściwość ma format wiadomości e-mail.[EmailAddress]: Validates that the property has an email format.
  • [Phone]: Sprawdza, czy właściwość ma format numeru telefonu.[Phone]: Validates that the property has a telephone number format.
  • [Range]: Sprawdza, czy wartość właściwości znajduje się w określonym zakresie.[Range]: Validates that the property value falls within a specified range.
  • [RegularExpression]: Sprawdza, czy wartość właściwości jest zgodna z określonym wyrażeniem regularnym.[RegularExpression]: Validates that the property value matches a specified regular expression.
  • [Required]: Sprawdza, czy pole nie ma wartości null.[Required]: Validates that the field is not null. Zobacz [Required] atrybut , aby uzyskać szczegółowe informacje o zachowaniu tego atrybutu.See [Required] attribute for details about this attribute's behavior.
  • [StringLength]: Sprawdza, czy wartość właściwości String nie przekracza podanego limitu długości.[StringLength]: Validates that a string property value doesn't exceed a specified length limit.
  • [Url]: Sprawdza, czy właściwość ma format adresu URL.[Url]: Validates that the property has a URL format.
  • [Remote]: Sprawdza poprawność danych wejściowych na kliencie przez wywołanie metody akcji na serwerze.[Remote]: Validates input on the client by calling an action method on the server. Zobacz [Remote] atrybut , aby uzyskać szczegółowe informacje o zachowaniu tego atrybutu.See [Remote] attribute for details about this attribute's behavior.

Pełną listę atrybutów sprawdzania poprawności można znaleźć w przestrzeni nazw System. ComponentModel. DataAnnotations .A complete list of validation attributes can be found in the System.ComponentModel.DataAnnotations namespace.

Komunikaty o błędachError messages

Atrybuty walidacji pozwalają określić komunikat o błędzie, który ma być wyświetlany dla nieprawidłowych danych wejściowych.Validation attributes let you specify the error message to be displayed for invalid input. Przykład:For example:

[StringLength(8, ErrorMessage = "Name length can't be more than 8.")]

Wewnętrznie atrybuty są wywoływane String.Format przy użyciu symbolu zastępczego dla nazwy pola i czasami dodatkowych symboli zastępczych.Internally, the attributes call String.Format with a placeholder for the field name and sometimes additional placeholders. Przykład:For example:

[StringLength(8, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 6)]

W przypadku zastosowania do Name Właściwości komunikat o błędzie utworzony przez poprzedni kod powinien mieć wartość "nazwa musi zawierać się w przedziale od 6 do 8".When applied to a Name property, the error message created by the preceding code would be "Name length must be between 6 and 8.".

Aby dowiedzieć się, które parametry są przesyłane do String.Format komunikatu o błędzie określonego atrybutu, zobacz kod źródłowy adnotacjidanych.To find out which parameters are passed to String.Format for a particular attribute's error message, see the DataAnnotations source code.

[Required] — atrybut[Required] attribute

System sprawdzania poprawności w programie .NET Core 3,0 lub nowszy traktuje parametry niedopuszczające wartości null lub właściwości powiązane tak, jakby miały [Required] atrybut.The validation system in .NET Core 3.0 and later treats non-nullable parameters or bound properties as if they had a [Required] attribute. Typy wartości , takie jak decimal i, int nie dopuszczają wartości null.Value types such as decimal and int are non-nullable. To zachowanie można wyłączyć przez skonfigurowanie SuppressImplicitRequiredAttributeForNonNullableReferenceTypes w programie Startup.ConfigureServices :This behavior can be disabled by configuring SuppressImplicitRequiredAttributeForNonNullableReferenceTypes in Startup.ConfigureServices:

services.AddControllers(options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);

[Wymagane] Walidacja na serwerze[Required] validation on the server

Na serwerze, wymagana wartość jest uważana za brakującą, jeśli właściwość ma wartość null.On the server, a required value is considered missing if the property is null. Pole niedopuszczające wartości null jest zawsze prawidłowe i [Required] komunikat o błędzie nie jest wyświetlany.A non-nullable field is always valid, and the [Required] attribute's error message is never displayed.

Jednak powiązanie modelu dla właściwości niedopuszczających wartości null może zakończyć się niepowodzeniem, co spowoduje wystąpienie komunikatu o błędzie, takiego jak The value '' is invalid .However, model binding for a non-nullable property may fail, resulting in an error message such as The value '' is invalid. Aby określić niestandardowy komunikat o błędzie dla weryfikacji po stronie serwera dla typów niedopuszczających wartości null, dostępne są następujące opcje:To specify a custom error message for server-side validation of non-nullable types, you have the following options:

  • Wprowadź wartość pola Nullable (np decimal? decimal . zamiast).Make the field nullable (for example, decimal? instead of decimal). Dopuszcza <T> wartość null typy wartości są traktowane jak standardowe typy dopuszczające wartości null.Nullable<T> value types are treated like standard nullable types.

  • Określ domyślny komunikat o błędzie, który ma być używany przez powiązanie modelu, jak pokazano w następującym przykładzie:Specify the default error message to be used by model binding, as shown in the following example:

    services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    services.AddSingleton<IValidationAttributeAdapterProvider,
        CustomValidationAttributeAdapterProvider>();
    

    Aby uzyskać więcej informacji o błędach powiązania modelu, dla których można ustawić domyślne komunikaty dla programu, zobacz DefaultModelBindingMessageProvider .For more information about model binding errors that you can set default messages for, see DefaultModelBindingMessageProvider.

[Wymagane] weryfikacja na kliencie[Required] validation on the client

Typy niedopuszczające wartości null i ciągi są obsługiwane inaczej na kliencie w porównaniu z serwerem.Non-nullable types and strings are handled differently on the client compared to the server. Na kliencie:On the client:

  • Wartość jest uważana za obecną tylko wtedy, gdy wprowadzono dla niej dane wejściowe.A value is considered present only if input is entered for it. W związku z tym, walidacja po stronie klienta obsługuje niedopuszczające wartości null typy takie same jak typy dopuszczające wartości null.Therefore, client-side validation handles non-nullable types the same as nullable types.
  • Biały znak w polu ciągu jest uznawany za prawidłowe dane wejściowe przez wymaganą metodę weryfikacji jQuery.Whitespace in a string field is considered valid input by the jQuery Validation required method. Walidacja po stronie serwera traktuje wymagane pole ciągu nieprawidłowe, jeśli wprowadzono tylko odstępy.Server-side validation considers a required string field invalid if only whitespace is entered.

Jak wspomniano wcześniej, typy niedopuszczające wartości null są traktowane tak, jakby miały [Required] atrybut.As noted earlier, non-nullable types are treated as though they had a [Required] attribute. Oznacza to, że można uzyskać weryfikację po stronie klienta, nawet jeśli nie zastosowano [Required] atrybutu.That means you get client-side validation even if you don't apply the [Required] attribute. Ale jeśli nie używasz tego atrybutu, zostanie wyświetlony domyślny komunikat o błędzie.But if you don't use the attribute, you get a default error message. Aby określić niestandardowy komunikat o błędzie, Użyj atrybutu.To specify a custom error message, use the attribute.

[Remote] — atrybut[Remote] attribute

Ten [Remote] atrybut implementuje walidację po stronie klienta, która wymaga wywołania metody na serwerze w celu określenia, czy dane wejściowe pola są prawidłowe.The [Remote] attribute implements client-side validation that requires calling a method on the server to determine whether field input is valid. Na przykład aplikacja może wymagać sprawdzenia, czy nazwa użytkownika jest już używana.For example, the app may need to verify whether a user name is already in use.

Aby zaimplementować zdalne sprawdzanie poprawności:To implement remote validation:

  1. Utwórz metodę akcji dla języka JavaScript do wywołania.Create an action method for JavaScript to call. Metoda zdalna walidacji jQuery oczekuje odpowiedzi JSON:The jQuery Validation remote method expects a JSON response:

    • true oznacza, że dane wejściowe są prawidłowe.true means the input data is valid.
    • false, undefined lub null oznacza, że dane wejściowe są nieprawidłowe.false, undefined, or null means the input is invalid. Wyświetl domyślny komunikat o błędzie.Display the default error message.
    • Każdy inny ciąg oznacza, że dane wejściowe są nieprawidłowe.Any other string means the input is invalid. Wyświetl ciąg jako niestandardowy komunikat o błędzie.Display the string as a custom error message.

    Oto przykład metody akcji, która zwraca niestandardowy komunikat o błędzie:Here's an example of an action method that returns a custom error message:

    [AcceptVerbs("GET", "POST")]
    public IActionResult VerifyEmail(string email)
    {
        if (!_userService.VerifyEmail(email))
        {
            return Json($"Email {email} is already in use.");
        }
    
        return Json(true);
    }
    
  2. W klasie modelu Dodaj adnotację do właściwości z atrybutem wskazującym na [Remote] metodę akcji walidacji, jak pokazano w następującym przykładzie:In the model class, annotate the property with a [Remote] attribute that points to the validation action method, as shown in the following example:

    [Remote(action: "VerifyEmail", controller: "Users")]
    public string Email { get; set; }
    

    Ten [Remote] atrybut znajduje się w Microsoft.AspNetCore.Mvc przestrzeni nazw.The [Remote] attribute is in the Microsoft.AspNetCore.Mvc namespace.

Dodatkowe polaAdditional fields

AdditionalFieldsWłaściwość [Remote] atrybutu umożliwia Weryfikowanie kombinacji pól względem danych na serwerze.The AdditionalFields property of the [Remote] attribute lets you validate combinations of fields against data on the server. Na przykład jeśli User model ma FirstName i LastName właściwości, można sprawdzić, czy żaden istniejący użytkownik już ma tę parę nazw.For example, if the User model had FirstName and LastName properties, you might want to verify that no existing users already have that pair of names. Poniższy przykład przedstawia sposób użycia AdditionalFields :The following example shows how to use AdditionalFields:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(LastName))]
[Display(Name = "First Name")]
public string FirstName { get; set; }

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName))]
[Display(Name = "Last Name")]
public string LastName { get; set; }

AdditionalFields można jawnie ustawić dla ciągów "FirstName" i "LastName", ale użycie operatora nameof upraszcza późniejsze refaktoryzacje.AdditionalFields could be set explicitly to the strings "FirstName" and "LastName", but using the nameof operator simplifies later refactoring. Metoda akcji dla tej walidacji musi akceptować zarówno firstName argumenty, jak i lastName :The action method for this validation must accept both firstName and lastName arguments:

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyName(string firstName, string lastName)
{
    if (!_userService.VerifyName(firstName, lastName))
    {
        return Json($"A user named {firstName} {lastName} already exists.");
    }

    return Json(true);
}

Gdy użytkownik wprowadzi imię lub nazwisko, kod JavaScript wykonuje zdalne wywołanie, aby sprawdzić, czy ta para nazw została podjęta.When the user enters a first or last name, JavaScript makes a remote call to see if that pair of names has been taken.

Aby sprawdzić poprawność dwóch lub więcej pól, podaj je jako listę rozdzielaną przecinkami.To validate two or more additional fields, provide them as a comma-delimited list. Na przykład aby dodać MiddleName Właściwość do modelu, należy ustawić [Remote] atrybut, jak pokazano w następującym przykładzie:For example, to add a MiddleName property to the model, set the [Remote] attribute as shown in the following example:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName) + "," + nameof(LastName))]
public string MiddleName { get; set; }

AdditionalFields, podobnie jak wszystkie argumenty atrybutu, musi być wyrażeniem stałym.AdditionalFields, like all attribute arguments, must be a constant expression. W związku z tym nie należy używać interpolowanego ciągu ani wywołania Join do inicjowania AdditionalFields .Therefore, don't use an interpolated string or call Join to initialize AdditionalFields.

Alternatywy dla wbudowanych atrybutówAlternatives to built-in attributes

Jeśli potrzebujesz weryfikacji niedostarczonej przez wbudowane atrybuty, możesz:If you need validation not provided by built-in attributes, you can:

Atrybuty niestandardoweCustom attributes

W przypadku scenariuszy, w których wbudowane atrybuty walidacji nie obsługują, można utworzyć niestandardowe atrybuty walidacji.For scenarios that the built-in validation attributes don't handle, you can create custom validation attributes. Utwórz klasę, która dziedziczy z ValidationAttribute , i Zastąp IsValid metodę.Create a class that inherits from ValidationAttribute, and override the IsValid method.

IsValidMetoda akceptuje obiekt o nazwie Value , czyli dane wejściowe do zweryfikowania.The IsValid method accepts an object named value , which is the input to be validated. Przeciążenie akceptuje również ValidationContext obiekt, który zawiera dodatkowe informacje, takie jak wystąpienie modelu utworzone przez powiązanie modelu.An overload also accepts a ValidationContext object, which provides additional information, such as the model instance created by model binding.

Poniższy przykład sprawdza, czy Data wydania filmu w klasycznym gatunku nie jest późniejsza niż określony rok.The following example validates that the release date for a movie in the Classic genre isn't later than a specified year. [ClassicMovie]Atrybut:The [ClassicMovie] attribute:

  • Jest uruchamiany tylko na serwerze.Is only run on the server.
  • W przypadku klasycznych filmów program sprawdza poprawność daty wydania:For Classic movies, validates the release date:
public class ClassicMovieAttribute : ValidationAttribute
{
    public ClassicMovieAttribute(int year)
    {
        Year = year;
    }

    public int Year { get; }

    public string GetErrorMessage() =>
        $"Classic movies must have a release year no later than {Year}.";

    protected override ValidationResult IsValid(object value,
        ValidationContext validationContext)
    {
        var movie = (Movie)validationContext.ObjectInstance;
        var releaseYear = ((DateTime)value).Year;

        if (movie.Genre == Genre.Classic && releaseYear > Year)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }
}

movieZmienna w poprzednim przykładzie reprezentuje Movie obiekt, który zawiera dane z przesłania formularza.The movie variable in the preceding example represents a Movie object that contains the data from the form submission. Gdy Walidacja nie powiedzie się, ValidationResult zostanie zwrócony komunikat o błędzie.When validation fails, a ValidationResult with an error message is returned.

IValidatableObjectIValidatableObject

Poprzedni przykład działa tylko z Movie typami.The preceding example works only with Movie types. Kolejną opcją weryfikacji na poziomie klasy jest implementacja IValidatableObject w klasie modelu, jak pokazano w następującym przykładzie:Another option for class-level validation is to implement IValidatableObject in the model class, as shown in the following example:

public class ValidatableMovie : IValidatableObject
{
    private const int _classicYear = 1960;

    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; }

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

    [Required]
    [StringLength(1000)]
    public string Description { get; set; }

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Genre == Genre.Classic && ReleaseDate.Year > _classicYear)
        {
            yield return new ValidationResult(
                $"Classic movies must have a release year no later than {_classicYear}.",
                new[] { nameof(ReleaseDate) });
        }
    }
}

Sprawdzanie poprawności węzła najwyższego poziomuTop-level node validation

Węzły najwyższego poziomu obejmują:Top-level nodes include:

  • Parametry akcjiAction parameters
  • Właściwości kontroleraController properties
  • Parametry procedury obsługi stronPage handler parameters
  • Właściwości modelu stronyPage model properties

Węzły najwyższego poziomu powiązane z modelem są weryfikowane jako uzupełnienie właściwości modelu.Model-bound top-level nodes are validated in addition to validating model properties. W poniższym przykładzie z przykładowej aplikacji VerifyPhone Metoda używa RegularExpressionAttribute do walidacji phone parametru Action:In the following example from the sample app, the VerifyPhone method uses the RegularExpressionAttribute to validate the phone action parameter:

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyPhone(
    [RegularExpression(@"^\d{3}-\d{3}-\d{4}$")] string phone)
{
    if (!ModelState.IsValid)
    {
        return Json($"Phone {phone} has an invalid format. Format: ###-###-####");
    }

    return Json(true);
}

Węzły najwyższego poziomu mogą korzystać BindRequiredAttribute z atrybutów walidacji.Top-level nodes can use BindRequiredAttribute with validation attributes. W poniższym przykładzie z przykładowej aplikacji CheckAge Metoda określa, że age parametr musi być powiązany z ciągu zapytania, gdy formularz zostanie przesłany:In the following example from the sample app, the CheckAge method specifies that the age parameter must be bound from the query string when the form is submitted:

[HttpPost]
public IActionResult CheckAge([BindRequired, FromQuery] int age)
{

Na stronie sprawdzanie wieku ( Sprawdź. cshtml ) Istnieją dwa formy.In the Check Age page ( CheckAge.cshtml ), there are two forms. Pierwszy formularz przesyła Age wartość 99 jako parametr ciągu zapytania: https://localhost:5001/Users/CheckAge?Age=99 .The first form submits an Age value of 99 as a query string parameter: https://localhost:5001/Users/CheckAge?Age=99.

Po przesłaniu poprawnie sformatowanego age parametru z ciągu zapytania, formularz sprawdza poprawność.When a properly formatted age parameter from the query string is submitted, the form validates.

Drugi formularz na stronie sprawdzanie wieku przesyła Age wartość w treści żądania, a Walidacja nie powiedzie się.The second form on the Check Age page submits the Age value in the body of the request, and validation fails. Powiązanie nie powiodło się, ponieważ age parametr musi pochodzić z ciągu zapytania.Binding fails because the age parameter must come from a query string.

Maksymalna liczba błędówMaximum errors

Walidacja jest zatrzymywana, gdy zostanie osiągnięta maksymalna liczba błędów (domyślnie 200).Validation stops when the maximum number of errors is reached (200 by default). Tę liczbę można skonfigurować przy użyciu następującego kodu w programie Startup.ConfigureServices :You can configure this number with the following code in Startup.ConfigureServices:

services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.MaxModelValidationErrors = 50;
        options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
            _ => "The field is required.");
    });

services.AddSingleton<IValidationAttributeAdapterProvider,
    CustomValidationAttributeAdapterProvider>();

Maksymalna rekursjaMaximum recursion

ValidationVisitor przechodzi do grafu obiektów sprawdzanego przez model.ValidationVisitor traverses the object graph of the model being validated. W przypadku modeli, które są głębokie lub nieskończonie cykliczne, walidacja może spowodować przepełnienie stosu.For models that are deep or are infinitely recursive, validation may result in stack overflow. MvcOptions. MaxValidationDepth umożliwia szybkie zakończenie sprawdzania poprawności, Jeśli rekursja odwiedzających przekracza skonfigurowaną głębokość.MvcOptions.MaxValidationDepth provides a way to stop validation early if the visitor recursion exceeds a configured depth. Wartość domyślna MvcOptions.MaxValidationDepth to 32.The default value of MvcOptions.MaxValidationDepth is 32.

Automatyczny krótki obwódAutomatic short-circuit

Sprawdzanie poprawności jest automatycznie skracane (pomijane), jeśli wykres modelu nie wymaga weryfikacji.Validation is automatically short-circuited (skipped) if the model graph doesn't require validation. Obiekty, dla których środowisko uruchomieniowe pomija sprawdzanie poprawności dla dołączania kolekcji elementów podstawowych (takich jak byte[] , string[] , Dictionary<string, string> ) i złożonych wykresów obiektów, które nie mają żadnych modułów sprawdzania poprawności.Objects that the runtime skips validation for include collections of primitives (such as byte[], string[], Dictionary<string, string>) and complex object graphs that don't have any validators.

Wyłącz weryfikacjęDisable validation

Aby wyłączyć weryfikację:To disable validation:

  1. Utwórz implementację IObjectModelValidator , która nie oznacza żadnych pól jako nieprawidłowych.Create an implementation of IObjectModelValidator that doesn't mark any fields as invalid.

    public class NullObjectModelValidator : IObjectModelValidator
    {
        public void Validate(ActionContext actionContext,
            ValidationStateDictionary validationState, string prefix, object model)
        {
    
        }
    }
    
  2. Dodaj następujący kod, aby Startup.ConfigureServices zastąpić domyślną IObjectModelValidator implementację w kontenerze iniekcji zależności.Add the following code to Startup.ConfigureServices to replace the default IObjectModelValidator implementation in the dependency injection container.

    services.AddSingleton<IObjectModelValidator, NullObjectModelValidator>();
    

Nadal mogą pojawić się błędy stanu modelu pochodzące z powiązania modelu.You might still see model state errors that originate from model binding.

Weryfikacja po stronie klientaClient-side validation

Weryfikacja po stronie klienta uniemożliwia przesyłanie, dopóki formularz nie będzie prawidłowy.Client-side validation prevents submission until the form is valid. Przycisk Prześlij uruchamia kod JavaScript, który przesyła formularz lub wyświetla komunikaty o błędach.The Submit button runs JavaScript that either submits the form or displays error messages.

Weryfikacja po stronie klienta umożliwia uniknięcie niepotrzebnej komunikacji z serwerem w przypadku błędów danych wejściowych w formularzu.Client-side validation avoids an unnecessary round trip to the server when there are input errors on a form. Następujący skrypt odwołuje się do _Layout. cshtml i _ValidationScriptsPartial. cshtml obsługuje walidację po stronie klienta:The following script references in _Layout.cshtml and _ValidationScriptsPartial.cshtml support client-side validation:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

Skrypt niezauważalnego sprawdzania poprawności jQuery jest niestandardową biblioteką frontonu firmy Microsoft, która kompiluje się w popularnej wtyczki do sprawdzania poprawności jQuery .The jQuery Unobtrusive Validation script is a custom Microsoft front-end library that builds on the popular jQuery Validation plugin. Bez dyskretnej weryfikacji jQuery należy wykonać kod tej samej logiki walidacji w dwóch miejscach: raz w atrybuty walidacji po stronie serwera we właściwościach modelu, a następnie ponownie w skryptach po stronie klienta.Without jQuery Unobtrusive Validation, you would have to code the same validation logic in two places: once in the server-side validation attributes on model properties, and then again in client-side scripts. Zamiast tego, pomocników tagów i pomocników HTML używają atrybutów walidacji i metadanych typu z właściwości modelu do renderowania atrybutów HTML 5 data- dla elementów formularza, które wymagają walidacji.Instead, Tag Helpers and HTML helpers use the validation attributes and type metadata from model properties to render HTML 5 data- attributes for the form elements that need validation. niezauważalne sprawdzenie poprawności przez program jQuery umożliwia przeanalizowanie data- atrybutów i przekazanie logiki do walidacji jQuery, efektywne "Kopiowanie" logiki walidacji po stronie serwera do klienta.jQuery Unobtrusive Validation parses the data- attributes and passes the logic to jQuery Validation, effectively "copying" the server-side validation logic to the client. Błędy sprawdzania poprawności można wyświetlić na kliencie przy użyciu pomocników tagów, jak pokazano poniżej:You can display validation errors on the client using tag helpers as shown here:

<div class="form-group">
    <label asp-for="Movie.ReleaseDate" class="control-label"></label>
    <input asp-for="Movie.ReleaseDate" class="form-control" />
    <span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>

Poprzednie pomocnicy tagów renderują następujący kod HTML:The preceding tag helpers render the following HTML:

<div class="form-group">
    <label class="control-label" for="Movie_ReleaseDate">Release Date</label>
    <input class="form-control" type="date" data-val="true"
        data-val-required="The Release Date field is required."
        id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">
    <span class="text-danger field-validation-valid"
        data-valmsg-for="Movie.ReleaseDate" data-valmsg-replace="true"></span>
</div>

Zauważ, że data- atrybuty w danych wyjściowych HTML odpowiadają atrybutom walidacji Movie.ReleaseDate właściwości.Notice that the data- attributes in the HTML output correspond to the validation attributes for the Movie.ReleaseDate property. Ten data-val-required atrybut zawiera komunikat o błędzie, który zostanie wyświetlony, jeśli użytkownik nie wypełni pola Data wydania.The data-val-required attribute contains an error message to display if the user doesn't fill in the release date field. niezauważalne sprawdzenie poprawności przez funkcję jQuery spowoduje przekazanie tej wartości do metody sprawdzania poprawności jQuery () , która następnie wyświetla ten komunikat w elemencie towarzyszącym <span> .jQuery Unobtrusive Validation passes this value to the jQuery Validation required() method, which then displays that message in the accompanying <span> element.

Walidacja typu danych jest oparta na typie .NET właściwości, chyba że zostanie zastąpiona przez [DataType] atrybut.Data type validation is based on the .NET type of a property, unless that is overridden by a [DataType] attribute. Przeglądarki mają własne domyślne komunikaty o błędach, ale pakietem weryfikacji jQuery nie dyskretnego sprawdzania poprawności może przesłonić te komunikaty.Browsers have their own default error messages, but the jQuery Validation Unobtrusive Validation package can override those messages. [DataType] atrybuty i podklasy, takie jak [EmailAddress] pozwalają określić komunikat o błędzie.[DataType] attributes and subclasses such as [EmailAddress] let you specify the error message.

Niezauważalna weryfikacjaUnobtrusive validation

Aby uzyskać informacje o niezauważalnej weryfikacji, zobacz ten problemw usłudze GitHub.For information on unobtrusive validation, see this GitHub issue.

Dodawanie walidacji do formularzy dynamicznychAdd Validation to Dynamic Forms

niezauważalne Walidacja w usłudze jQuery powoduje przekazanie logiki walidacji i parametrów do walidacji jQuery podczas pierwszego ładowania strony.jQuery Unobtrusive Validation passes validation logic and parameters to jQuery Validation when the page first loads. W związku z tym sprawdzanie poprawności nie działa automatycznie na formularzach generowanych dynamicznie.Therefore, validation doesn't work automatically on dynamically generated forms. Aby włączyć weryfikację, poinformuj jQuery o niezauważalnej weryfikacji, aby przeanalizować formularz dynamiczny bezpośrednio po jego utworzeniu.To enable validation, tell jQuery Unobtrusive Validation to parse the dynamic form immediately after you create it. Na przykład poniższy kod konfiguruje walidację po stronie klienta w formularzu dodanym przez AJAX.For example, the following code sets up client-side validation on a form added via AJAX.

$.get({
    url: "https://url/that/returns/a/form",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add form. " + errorThrown);
    },
    success: function(newFormHTML) {
        var container = document.getElementById("form-container");
        container.insertAdjacentHTML("beforeend", newFormHTML);
        var forms = container.getElementsByTagName("form");
        var newForm = forms[forms.length - 1];
        $.validator.unobtrusive.parse(newForm);
    }
})

$.validator.unobtrusive.parse()Metoda akceptuje selektor jQuery dla jednego argumentu.The $.validator.unobtrusive.parse() method accepts a jQuery selector for its one argument. Ta metoda informuje niedyskretną weryfikację jQuery do analizy data- atrybutów formularzy w ramach tego selektora.This method tells jQuery Unobtrusive Validation to parse the data- attributes of forms within that selector. Wartości tych atrybutów są następnie przesyłane do wtyczki walidacji jQuery.The values of those attributes are then passed to the jQuery Validation plugin.

Dodawanie walidacji do formantów dynamicznychAdd Validation to Dynamic Controls

$.validator.unobtrusive.parse()Metoda działa na całym formularzu, a nie na poszczególnych dynamicznie generowanych kontrolkach, takich jak <input> i <select/> .The $.validator.unobtrusive.parse() method works on an entire form, not on individual dynamically generated controls, such as <input> and <select/>. Aby przeanalizować formularz, Usuń dane sprawdzania poprawności, które zostały dodane, gdy formularz został wcześniej przeanalizowany, jak pokazano w następującym przykładzie:To reparse the form, remove the validation data that was added when the form was parsed earlier, as shown in the following example:

$.get({
    url: "https://url/that/returns/a/control",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add control. " + errorThrown);
    },
    success: function(newInputHTML) {
        var form = document.getElementById("my-form");
        form.insertAdjacentHTML("beforeend", newInputHTML);
        $(form).removeData("validator")    // Added by jQuery Validation
               .removeData("unobtrusiveValidation");   // Added by jQuery Unobtrusive Validation
        $.validator.unobtrusive.parse(form);
    }
})

Niestandardowe sprawdzanie poprawności po stronie klientaCustom client-side validation

Niestandardowe sprawdzanie poprawności po stronie klienta jest wykonywane przez generowanie data- atrybutów HTML, które działają z niestandardowym adapterem weryfikacji platformy jQuery.Custom client-side validation is done by generating data- HTML attributes that work with a custom jQuery Validation adapter. Następujący przykładowy kod karty został zapisany dla [ClassicMovie] [ClassicMovieWithClientValidator] atrybutów i, które zostały wprowadzone wcześniej w tym artykule:The following sample adapter code was written for the [ClassicMovie] and [ClassicMovieWithClientValidator] attributes that were introduced earlier in this article:

$.validator.addMethod('classicmovie', function (value, element, params) {
    var genre = $(params[0]).val(), year = params[1], date = new Date(value);

    // The Classic genre has a value of '0'.
    if (genre && genre.length > 0 && genre[0] === '0') {
        // The release date for a Classic is valid if it's no greater than the given year.
        return date.getUTCFullYear() <= year;
    }

    return true;
});

$.validator.unobtrusive.adapters.add('classicmovie', ['year'], function (options) {
    var element = $(options.form).find('select#Movie_Genre')[0];

    options.rules['classicmovie'] = [element, parseInt(options.params['year'])];
    options.messages['classicmovie'] = options.message;
});

Aby uzyskać informacje o sposobach pisania kart sieciowych, zobacz dokumentację dotyczącą weryfikacji jQuery.For information about how to write adapters, see the jQuery Validation documentation.

Użycie karty dla danego pola jest wyzwalane przez data- atrybuty, które:The use of an adapter for a given field is triggered by data- attributes that:

  • Oznacz pole jako podlegające walidacji ( data-val="true" ).Flag the field as being subject to validation (data-val="true").
  • Zidentyfikuj nazwę reguły walidacji i tekst komunikatu o błędzie (na przykład data-val-rulename="Error message." ).Identify a validation rule name and error message text (for example, data-val-rulename="Error message.").
  • Podaj wszelkie dodatkowe parametry wymagane przez moduł sprawdzania poprawności (na przykład data-val-rulename-param1="value" ).Provide any additional parameters the validator needs (for example, data-val-rulename-param1="value").

W poniższym przykładzie przedstawiono data- atrybuty dla atrybutu przykładowej aplikacji ClassicMovie :The following example shows the data- attributes for the sample app's ClassicMovie attribute:

<input class="form-control" type="date"
    data-val="true"
    data-val-classicmovie="Classic movies must have a release year no later than 1960."
    data-val-classicmovie-year="1960"
    data-val-required="The Release Date field is required."
    id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">

Jak wspomniano wcześniej, pomocników tagów i pomocników HTML wykorzystują informacje z atrybutów walidacji do renderowania data- atrybutów.As noted earlier, Tag Helpers and HTML helpers use information from validation attributes to render data- attributes. Istnieją dwie opcje pisania kodu, które powoduje tworzenie niestandardowych data- atrybutów HTML:There are two options for writing code that results in the creation of custom data- HTML attributes:

  • Utwórz klasę, która pochodzi od AttributeAdapterBase<TAttribute> i klasy implementującej IValidationAttributeAdapterProvider , i Zarejestruj swój atrybut oraz jego kartę w programie di.Create a class that derives from AttributeAdapterBase<TAttribute> and a class that implements IValidationAttributeAdapterProvider, and register your attribute and its adapter in DI. Ta metoda jest zgodna z pojedynczym podmiotem odpowiedzialnym w odniesieniu do kodu weryfikacyjnego związanego z serwerem i klienta jest w osobnych klasach.This method follows the single responsibility principal in that server-related and client-related validation code is in separate classes. Adapter ma również zalety, że ponieważ jest on zarejestrowany w programie DI, w razie potrzeby są dostępne inne usługi w programie DI.The adapter also has the advantage that since it is registered in DI, other services in DI are available to it if needed.
  • Zaimplementuj IClientModelValidator w ValidationAttribute klasie.Implement IClientModelValidator in your ValidationAttribute class. Ta metoda może być odpowiednia, jeśli atrybut nie wykonuje walidacji po stronie serwera i nie wymaga żadnych usług z programu DI.This method might be appropriate if the attribute doesn't do any server-side validation and doesn't need any services from DI.

AttributeAdapter dla weryfikacji po stronie klientaAttributeAdapter for client-side validation

Ta metoda renderowania data- atrybutów w kodzie HTML jest używana przez ClassicMovie atrybut w przykładowej aplikacji.This method of rendering data- attributes in HTML is used by the ClassicMovie attribute in the sample app. Aby dodać weryfikację klienta przy użyciu tej metody:To add client validation by using this method:

  1. Utwórz klasę adaptera atrybutów dla niestandardowego atrybutu walidacji.Create an attribute adapter class for the custom validation attribute. Utwórz klasę z AttributeAdapterBase <T> .Derive the class from AttributeAdapterBase<T>. Utwórz AddValidation metodę, która dodaje data- atrybuty do renderowanych danych wyjściowych, jak pokazano w tym przykładzie:Create an AddValidation method that adds data- attributes to the rendered output, as shown in this example:

    public class ClassicMovieAttributeAdapter : AttributeAdapterBase<ClassicMovieAttribute>
    {
        public ClassicMovieAttributeAdapter(ClassicMovieAttribute attribute,
            IStringLocalizer stringLocalizer)
            : base(attribute, stringLocalizer)
        {
    
        }
    
        public override void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage(context));
    
            var year = Attribute.Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public override string GetErrorMessage(ModelValidationContextBase validationContext) =>
            Attribute.GetErrorMessage();
    }
    
  2. Utwórz klasę dostawcy kart implementującą IValidationAttributeAdapterProvider .Create an adapter provider class that implements IValidationAttributeAdapterProvider. W GetAttributeAdapter metodzie Przekaż atrybut niestandardowy do konstruktora adaptera, jak pokazano w tym przykładzie:In the GetAttributeAdapter method pass in the custom attribute to the adapter's constructor, as shown in this example:

    public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
    {
        private readonly IValidationAttributeAdapterProvider baseProvider =
            new ValidationAttributeAdapterProvider();
    
        public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute,
            IStringLocalizer stringLocalizer)
        {
            if (attribute is ClassicMovieAttribute classicMovieAttribute)
            {
                return new ClassicMovieAttributeAdapter(classicMovieAttribute, stringLocalizer);
            }
    
            return baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
        }
    }
    
  3. Zarejestruj dostawcę karty dla DI in Startup.ConfigureServices :Register the adapter provider for DI in Startup.ConfigureServices:

    services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    services.AddSingleton<IValidationAttributeAdapterProvider,
        CustomValidationAttributeAdapterProvider>();
    

IClientModelValidator dla weryfikacji po stronie klientaIClientModelValidator for client-side validation

Ta metoda renderowania data- atrybutów w kodzie HTML jest używana przez ClassicMovieWithClientValidator atrybut w przykładowej aplikacji.This method of rendering data- attributes in HTML is used by the ClassicMovieWithClientValidator attribute in the sample app. Aby dodać weryfikację klienta przy użyciu tej metody:To add client validation by using this method:

  • W atrybucie niestandardowego sprawdzania poprawności Zaimplementuj IClientModelValidator interfejs i Utwórz AddValidation metodę.In the custom validation attribute, implement the IClientModelValidator interface and create an AddValidation method. W AddValidation metodzie Dodaj data- atrybuty do walidacji, jak pokazano w następującym przykładzie:In the AddValidation method, add data- attributes for validation, as shown in the following example:

    public class ClassicMovieWithClientValidatorAttribute :
        ValidationAttribute, IClientModelValidator
    {
        public ClassicMovieWithClientValidatorAttribute(int year)
        {
            Year = year;
        }
    
        public int Year { get; }
    
        public void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());
    
            var year = Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public string GetErrorMessage() =>
            $"Classic movies must have a release year no later than {Year}.";
    
        protected override ValidationResult IsValid(object value,
            ValidationContext validationContext)
        {
            var movie = (Movie)validationContext.ObjectInstance;
            var releaseYear = ((DateTime)value).Year;
    
            if (movie.Genre == Genre.Classic && releaseYear > Year)
            {
                return new ValidationResult(GetErrorMessage());
            }
    
            return ValidationResult.Success;
        }
    
        private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (attributes.ContainsKey(key))
            {
                return false;
            }
    
            attributes.Add(key, value);
            return true;
        }
    }
    

Wyłącz weryfikację po stronie klientaDisable client-side validation

Poniższy kod wyłącza weryfikację klienta na Razor stronach:The following code disables client validation in Razor Pages:

services.AddRazorPages()
    .AddViewOptions(options =>
    {
        options.HtmlHelperOptions.ClientValidationEnabled = false;
    });

Inne opcje wyłączenia weryfikacji po stronie klienta:Other options to disable client-side validation:

  • Dodaj komentarz do odwołania do _ValidationScriptsPartial wszystkich plików . cshtml .Comment out the reference to _ValidationScriptsPartial in all the .cshtml files.
  • Usuń zawartość pliku Pages\Shared _ ValidationScriptsPartial. cshtml .Remove the contents of the Pages\Shared_ValidationScriptsPartial.cshtml file.

Poprzednie podejście nie zapobiega weryfikacji po stronie klienta ASP.NET Core Identity Razor biblioteki klas.The preceding approach won't prevent client side validation of ASP.NET Core Identity Razor Class Library. Aby uzyskać więcej informacji, zobacz Szkielet Identity w projektach ASP.NET Core.For more information, see Szkielet Identity w projektach ASP.NET Core.

Dodatkowe zasobyAdditional resources

W tym artykule wyjaśniono, jak sprawdzić poprawność danych wprowadzonych przez użytkownika w aplikacji ASP.NET Core MVC lub Razor Pages.This article explains how to validate user input in an ASP.NET Core MVC or Razor Pages app.

Wyświetlanie lub Pobieranie przykładowego kodu (jak pobrać).View or download sample code (how to download).

Stan modeluModel state

Stan modelu reprezentuje błędy pochodzące z dwóch podsystemów: powiązanie modelu i walidacja modelu.Model state represents errors that come from two subsystems: model binding and model validation. Błędy, które pochodzą z powiązania modelu , to zwykle Błędy konwersji danych (na przykład "x" jest wprowadzany w polu, w którym jest oczekiwana liczba całkowita).Errors that originate from model binding are generally data conversion errors (for example, an "x" is entered in a field that expects an integer). Walidacja modelu odbywa się po powiązaniu modelu i zgłasza błędy, gdy dane nie są zgodne z regułami biznesowymi (na przykład wartość 0 jest wprowadzana w polu, w którym oczekiwana jest Ocena z zakresu od 1 do 5).Model validation occurs after model binding and reports errors where the data doesn't conform to business rules (for example, a 0 is entered in a field that expects a rating between 1 and 5).

Zarówno powiązanie modelu, jak i walidacja są wykonywane przed wykonaniem akcji kontrolera lub Razor metody obsługi stron.Both model binding and validation occur before the execution of a controller action or a Razor Pages handler method. W przypadku aplikacji sieci Web jest odpowiedzialna za jej sprawdzenie ModelState.IsValid i reagowanie.For web apps, it's the app's responsibility to inspect ModelState.IsValid and react appropriately. Aplikacja internetowa zazwyczaj ponownie wyświetla stronę z komunikatem o błędzie:Web apps typically redisplay the page with an error message:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Kontrolery interfejsu API sieci Web nie muszą sprawdzać ModelState.IsValid , czy mają [ApiController] atrybut.Web API controllers don't have to check ModelState.IsValid if they have the [ApiController] attribute. W takim przypadku automatyczna odpowiedź HTTP 400 zawierająca szczegóły błędu jest zwracana, gdy stan modelu jest nieprawidłowy.In that case, an automatic HTTP 400 response containing error details is returned when model state is invalid. Aby uzyskać więcej informacji, zobacz Automatyczne HTTP 400 odpowiedzi.For more information, see Automatic HTTP 400 responses.

Uruchom ponownie weryfikacjęRerun validation

Walidacja jest automatyczna, ale warto powtórzyć ją ręcznie.Validation is automatic, but you might want to repeat it manually. Na przykład można obliczyć wartość właściwości i chcieć ponownie uruchomić weryfikację po ustawieniu właściwości na wartość obliczaną.For example, you might compute a value for a property and want to rerun validation after setting the property to the computed value. Aby ponownie uruchomić weryfikację, wywołaj TryValidateModel metodę, jak pokazano poniżej:To rerun validation, call the TryValidateModel method, as shown here:

var movie = new Movie
{
    Title = title,
    Genre = genre,
    ReleaseDate = modifiedReleaseDate,
    Description = description,
    Price = price,
    Preorder = preorder,
};

TryValidateModel(movie);

if (ModelState.IsValid)
{
    _context.AddMovie(movie);
    _context.SaveChanges();

    return RedirectToAction(actionName: nameof(Index));
}

return View(movie);

Atrybuty walidacjiValidation attributes

Atrybuty walidacji umożliwiają określanie reguł walidacji dla właściwości modelu.Validation attributes let you specify validation rules for model properties. W poniższym przykładzie z przykładowej aplikacji przedstawiono klasę modelu, która ma adnotację z atrybutami walidacji.The following example from the sample app shows a model class that is annotated with validation attributes. Ten [ClassicMovie] atrybut jest niestandardowym atrybutem walidacji, a inne są wbudowane.The [ClassicMovie] attribute is a custom validation attribute and the others are built-in. Niepokazywany jest [ClassicMovie2] , który pokazuje alternatywny sposób implementacji atrybutu niestandardowego.Not shown is [ClassicMovie2], which shows an alternative way to implement a custom attribute.

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

    [Required]
    [StringLength(100)]
    public string Title { get; set; }

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

    [Required]
    [StringLength(1000)]
    public string Description { get; set; }

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    [Required]
    public Genre Genre { get; set; }

    public bool Preorder { get; set; }
}

Atrybuty wbudowaneBuilt-in attributes

Wbudowane atrybuty walidacji obejmują:Built-in validation attributes include:

  • [CreditCard]: Sprawdza, czy właściwość ma format karty kredytowej.[CreditCard]: Validates that the property has a credit card format.
  • [Compare]: Sprawdza, czy dwie właściwości w modelu pasują do siebie.[Compare]: Validates that two properties in a model match. Na przykład plik register.cshtml.cs używa [Compare] do sprawdzania poprawności dwóch wprowadzonych haseł.For example, the Register.cshtml.cs file uses [Compare] to validate the two entered passwords match. Szkielet Identity Aby wyświetlić kod rejestru.Scaffold Identity to see the Register code.
  • [EmailAddress]: Sprawdza, czy właściwość ma format wiadomości e-mail.[EmailAddress]: Validates that the property has an email format.
  • [Phone]: Sprawdza, czy właściwość ma format numeru telefonu.[Phone]: Validates that the property has a telephone number format.
  • [Range]: Sprawdza, czy wartość właściwości znajduje się w określonym zakresie.[Range]: Validates that the property value falls within a specified range.
  • [RegularExpression]: Sprawdza, czy wartość właściwości jest zgodna z określonym wyrażeniem regularnym.[RegularExpression]: Validates that the property value matches a specified regular expression.
  • [Required]: Sprawdza, czy pole nie ma wartości null.[Required]: Validates that the field is not null. Zobacz [Required] atrybut , aby uzyskać szczegółowe informacje o zachowaniu tego atrybutu.See [Required] attribute for details about this attribute's behavior.
  • [StringLength]: Sprawdza, czy wartość właściwości String nie przekracza podanego limitu długości.[StringLength]: Validates that a string property value doesn't exceed a specified length limit.
  • [Url]: Sprawdza, czy właściwość ma format adresu URL.[Url]: Validates that the property has a URL format.
  • [Remote]: Sprawdza poprawność danych wejściowych na kliencie przez wywołanie metody akcji na serwerze.[Remote]: Validates input on the client by calling an action method on the server. Zobacz [Remote] atrybut , aby uzyskać szczegółowe informacje o zachowaniu tego atrybutu.See [Remote] attribute for details about this attribute's behavior.

W przypadku używania [RegularExpression] atrybutu z walidacją po stronie klienta wyrażenie regularne jest wykonywane w języku JavaScript na kliencie.When using the [RegularExpression] attribute with client-side validation, the regex is executed in JavaScript on the client. Oznacza to, że będzie używane zachowanie zgodne ze standardem ECMAScript .This means ECMAScript matching behavior will be used. Aby uzyskać więcej informacji, zobacz ten problemw serwisie GitHub.For more information, see this GitHub issue.

Pełną listę atrybutów sprawdzania poprawności można znaleźć w przestrzeni nazw System. ComponentModel. DataAnnotations .A complete list of validation attributes can be found in the System.ComponentModel.DataAnnotations namespace.

Komunikaty o błędachError messages

Atrybuty walidacji pozwalają określić komunikat o błędzie, który ma być wyświetlany dla nieprawidłowych danych wejściowych.Validation attributes let you specify the error message to be displayed for invalid input. Przykład:For example:

[StringLength(8, ErrorMessage = "Name length can't be more than 8.")]

Wewnętrznie atrybuty są wywoływane String.Format przy użyciu symbolu zastępczego dla nazwy pola i czasami dodatkowych symboli zastępczych.Internally, the attributes call String.Format with a placeholder for the field name and sometimes additional placeholders. Przykład:For example:

[StringLength(8, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 6)]

W przypadku zastosowania do Name Właściwości komunikat o błędzie utworzony przez poprzedni kod powinien mieć wartość "nazwa musi zawierać się w przedziale od 6 do 8".When applied to a Name property, the error message created by the preceding code would be "Name length must be between 6 and 8.".

Aby dowiedzieć się, które parametry są przesyłane do String.Format komunikatu o błędzie określonego atrybutu, zobacz kod źródłowy adnotacjidanych.To find out which parameters are passed to String.Format for a particular attribute's error message, see the DataAnnotations source code.

[Required] — atrybut[Required] attribute

Domyślnie system walidacji traktuje niedopuszczające wartości null parametry lub właściwości tak, jakby miały [Required] atrybut.By default, the validation system treats non-nullable parameters or properties as if they had a [Required] attribute. Typy wartości , takie jak decimal i, int nie dopuszczają wartości null.Value types such as decimal and int are non-nullable.

[Wymagane] Walidacja na serwerze[Required] validation on the server

Na serwerze, wymagana wartość jest uważana za brakującą, jeśli właściwość ma wartość null.On the server, a required value is considered missing if the property is null. Pole niedopuszczające wartości null jest zawsze prawidłowe, a komunikat o błędzie [Required] nie jest nigdy wyświetlany.A non-nullable field is always valid, and the [Required] attribute's error message is never displayed.

Jednak powiązanie modelu dla właściwości niedopuszczających wartości null może zakończyć się niepowodzeniem, co spowoduje wystąpienie komunikatu o błędzie, takiego jak The value '' is invalid .However, model binding for a non-nullable property may fail, resulting in an error message such as The value '' is invalid. Aby określić niestandardowy komunikat o błędzie dla weryfikacji po stronie serwera dla typów niedopuszczających wartości null, dostępne są następujące opcje:To specify a custom error message for server-side validation of non-nullable types, you have the following options:

  • Wprowadź wartość pola Nullable (np decimal? decimal . zamiast).Make the field nullable (for example, decimal? instead of decimal). Dopuszcza <T> wartość null typy wartości są traktowane jak standardowe typy dopuszczające wartości null.Nullable<T> value types are treated like standard nullable types.

  • Określ domyślny komunikat o błędzie, który ma być używany przez powiązanie modelu, jak pokazano w następującym przykładzie:Specify the default error message to be used by model binding, as shown in the following example:

    services.AddMvc(options => 
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                (_) => "The field is required.");
        })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddSingleton
        <IValidationAttributeAdapterProvider, 
         CustomValidationAttributeAdapterProvider>();
    

    Aby uzyskać więcej informacji o błędach powiązania modelu, dla których można ustawić domyślne komunikaty dla programu, zobacz DefaultModelBindingMessageProvider .For more information about model binding errors that you can set default messages for, see DefaultModelBindingMessageProvider.

[Wymagane] weryfikacja na kliencie[Required] validation on the client

Typy niedopuszczające wartości null i ciągi są obsługiwane inaczej na kliencie w porównaniu z serwerem.Non-nullable types and strings are handled differently on the client compared to the server. Na kliencie:On the client:

  • Wartość jest uważana za obecną tylko wtedy, gdy wprowadzono dla niej dane wejściowe.A value is considered present only if input is entered for it. W związku z tym, walidacja po stronie klienta obsługuje niedopuszczające wartości null typy takie same jak typy dopuszczające wartości null.Therefore, client-side validation handles non-nullable types the same as nullable types.
  • Biały znak w polu ciągu jest uznawany za prawidłowe dane wejściowe przez wymaganą metodę weryfikacji jQuery.Whitespace in a string field is considered valid input by the jQuery Validation required method. Walidacja po stronie serwera traktuje wymagane pole ciągu nieprawidłowe, jeśli wprowadzono tylko odstępy.Server-side validation considers a required string field invalid if only whitespace is entered.

Jak wspomniano wcześniej, typy niedopuszczające wartości null są traktowane tak, jakby miały [Required] atrybut.As noted earlier, non-nullable types are treated as though they had a [Required] attribute. Oznacza to, że można uzyskać weryfikację po stronie klienta, nawet jeśli nie zastosowano [Required] atrybutu.That means you get client-side validation even if you don't apply the [Required] attribute. Ale jeśli nie używasz tego atrybutu, zostanie wyświetlony domyślny komunikat o błędzie.But if you don't use the attribute, you get a default error message. Aby określić niestandardowy komunikat o błędzie, Użyj atrybutu.To specify a custom error message, use the attribute.

[Remote] — atrybut[Remote] attribute

Ten [Remote] atrybut implementuje walidację po stronie klienta, która wymaga wywołania metody na serwerze w celu określenia, czy dane wejściowe pola są prawidłowe.The [Remote] attribute implements client-side validation that requires calling a method on the server to determine whether field input is valid. Na przykład aplikacja może wymagać sprawdzenia, czy nazwa użytkownika jest już używana.For example, the app may need to verify whether a user name is already in use.

Aby zaimplementować zdalne sprawdzanie poprawności:To implement remote validation:

  1. Utwórz metodę akcji dla języka JavaScript do wywołania.Create an action method for JavaScript to call. Metoda zdalna walidacji jQuery oczekuje odpowiedzi JSON:The jQuery Validate remote method expects a JSON response:

    • "true" oznacza, że dane wejściowe są prawidłowe."true" means the input data is valid.
    • "false", undefined lub null oznacza, że dane wejściowe są nieprawidłowe."false", undefined, or null means the input is invalid. Wyświetl domyślny komunikat o błędzie.Display the default error message.
    • Każdy inny ciąg oznacza, że dane wejściowe są nieprawidłowe.Any other string means the input is invalid. Wyświetl ciąg jako niestandardowy komunikat o błędzie.Display the string as a custom error message.

    Oto przykład metody akcji, która zwraca niestandardowy komunikat o błędzie:Here's an example of an action method that returns a custom error message:

    [AcceptVerbs("Get", "Post")]
    public IActionResult VerifyEmail(string email)
    {
        if (!_userRepository.VerifyEmail(email))
        {
            return Json($"Email {email} is already in use.");
        }
    
        return Json(true);
    }
    
  2. W klasie modelu Dodaj adnotację do właściwości z atrybutem wskazującym na [Remote] metodę akcji walidacji, jak pokazano w następującym przykładzie:In the model class, annotate the property with a [Remote] attribute that points to the validation action method, as shown in the following example:

    [Remote(action: "VerifyEmail", controller: "Users")]
    public string Email { get; set; }
    

    Ten [Remote] atrybut znajduje się w Microsoft.AspNetCore.Mvc przestrzeni nazw.The [Remote] attribute is in the Microsoft.AspNetCore.Mvc namespace. Zainstaluj pakiet NuGet Microsoft. AspNetCore. MVC. ViewFeatures , jeśli nie używasz programu Microsoft.AspNetCore.App lub Microsoft.AspNetCore.All pakietu.Install the Microsoft.AspNetCore.Mvc.ViewFeatures NuGet package if you're not using the Microsoft.AspNetCore.App or Microsoft.AspNetCore.All metapackage.

Dodatkowe polaAdditional fields

AdditionalFieldsWłaściwość [Remote] atrybutu umożliwia Weryfikowanie kombinacji pól względem danych na serwerze.The AdditionalFields property of the [Remote] attribute lets you validate combinations of fields against data on the server. Na przykład jeśli User model ma FirstName i LastName właściwości, można sprawdzić, czy żaden istniejący użytkownik już ma tę parę nazw.For example, if the User model had FirstName and LastName properties, you might want to verify that no existing users already have that pair of names. Poniższy przykład przedstawia sposób użycia AdditionalFields :The following example shows how to use AdditionalFields:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(LastName))]
public string FirstName { get; set; }
[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName))]
public string LastName { get; set; }

AdditionalFields może być jawnie ustawiona dla ciągów "FirstName" i "LastName" , ale użycie operatora nameof upraszcza późniejsze refaktoryzacje.AdditionalFields could be set explicitly to the strings "FirstName" and "LastName", but using the nameof operator simplifies later refactoring. Metoda akcji dla tej weryfikacji musi akceptować zarówno imiona, jak i nazwiska:The action method for this validation must accept both first name and last name arguments:

[AcceptVerbs("Get", "Post")]
public IActionResult VerifyName(string firstName, string lastName)
{
    if (!_userRepository.VerifyName(firstName, lastName))
    {
        return Json($"A user named {firstName} {lastName} already exists.");
    }

    return Json(true);
}

Gdy użytkownik wprowadzi imię lub nazwisko, kod JavaScript wykonuje zdalne wywołanie, aby sprawdzić, czy ta para nazw została podjęta.When the user enters a first or last name, JavaScript makes a remote call to see if that pair of names has been taken.

Aby sprawdzić poprawność dwóch lub więcej pól, podaj je jako listę rozdzielaną przecinkami.To validate two or more additional fields, provide them as a comma-delimited list. Na przykład aby dodać MiddleName Właściwość do modelu, należy ustawić [Remote] atrybut, jak pokazano w następującym przykładzie:For example, to add a MiddleName property to the model, set the [Remote] attribute as shown in the following example:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName) + "," + nameof(LastName))]
public string MiddleName { get; set; }

AdditionalFields, podobnie jak wszystkie argumenty atrybutu, musi być wyrażeniem stałym.AdditionalFields, like all attribute arguments, must be a constant expression. W związku z tym nie należy używać interpolowanego ciągu ani wywołania Join do inicjowania AdditionalFields .Therefore, don't use an interpolated string or call Join to initialize AdditionalFields.

Alternatywy dla wbudowanych atrybutówAlternatives to built-in attributes

Jeśli potrzebujesz weryfikacji niedostarczonej przez wbudowane atrybuty, możesz:If you need validation not provided by built-in attributes, you can:

Atrybuty niestandardoweCustom attributes

W przypadku scenariuszy, w których wbudowane atrybuty walidacji nie obsługują, można utworzyć niestandardowe atrybuty walidacji.For scenarios that the built-in validation attributes don't handle, you can create custom validation attributes. Utwórz klasę, która dziedziczy z ValidationAttribute , i Zastąp IsValid metodę.Create a class that inherits from ValidationAttribute, and override the IsValid method.

IsValidMetoda akceptuje obiekt o nazwie Value , czyli dane wejściowe do zweryfikowania.The IsValid method accepts an object named value , which is the input to be validated. Przeciążenie akceptuje również ValidationContext obiekt, który zawiera dodatkowe informacje, takie jak wystąpienie modelu utworzone przez powiązanie modelu.An overload also accepts a ValidationContext object, which provides additional information, such as the model instance created by model binding.

Poniższy przykład sprawdza, czy Data wydania filmu w klasycznym gatunku nie jest późniejsza niż określony rok.The following example validates that the release date for a movie in the Classic genre isn't later than a specified year. Ten [ClassicMovie2] atrybut najpierw sprawdza gatunek i kontynuuje działanie tylko wtedy, gdy jest on klasyczny .The [ClassicMovie2] attribute checks the genre first and continues only if it's Classic . W przypadku filmów identyfikowanych jako Classics sprawdza datę wydania, aby upewnić się, że nie jest ona późniejsza niż limit przesłany do konstruktora atrybutu.For movies identified as classics, it checks the release date to make sure it's not later than the limit passed to the attribute constructor.)

public class ClassicMovieAttribute : ValidationAttribute
{
    private int _year;

    public ClassicMovieAttribute(int year)
    {
        _year = year;
    }

    protected override ValidationResult IsValid(
        object value, ValidationContext validationContext)
    {
        var movie = (Movie)validationContext.ObjectInstance;
        var releaseYear = ((DateTime)value).Year;

        if (movie.Genre == Genre.Classic && releaseYear > _year)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }

    public int Year => _year;

    public string GetErrorMessage()
    {
        return $"Classic movies must have a release year no later than {_year}.";
    }
}

movieZmienna w poprzednim przykładzie reprezentuje Movie obiekt, który zawiera dane z przesłania formularza.The movie variable in the preceding example represents a Movie object that contains the data from the form submission. IsValidMetoda sprawdza datę i gatunek.The IsValid method checks the date and genre. Po pomyślnej weryfikacji program IsValid zwraca ValidationResult.Success kod.Upon successful validation, IsValid returns a ValidationResult.Success code. Gdy Walidacja nie powiedzie się, ValidationResult zostanie zwrócony komunikat o błędzie.When validation fails, a ValidationResult with an error message is returned.

IValidatableObjectIValidatableObject

Poprzedni przykład działa tylko z Movie typami.The preceding example works only with Movie types. Kolejną opcją weryfikacji na poziomie klasy jest implementacja IValidatableObject w klasie modelu, jak pokazano w następującym przykładzie:Another option for class-level validation is to implement IValidatableObject in the model class, as shown in the following example:

public class MovieIValidatable : IValidatableObject
{
    private const int _classicYear = 1960;

    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; }

    [Required]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; }

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    [Required]
    public Genre Genre { get; set; }

    public bool Preorder { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Genre == Genre.Classic && ReleaseDate.Year > _classicYear)
        {
            yield return new ValidationResult(
                $"Classic movies must have a release year earlier than {_classicYear}.",
                new[] { "ReleaseDate" });
        }
    }
}

Sprawdzanie poprawności węzła najwyższego poziomuTop-level node validation

Węzły najwyższego poziomu obejmują:Top-level nodes include:

  • Parametry akcjiAction parameters
  • Właściwości kontroleraController properties
  • Parametry procedury obsługi stronPage handler parameters
  • Właściwości modelu stronyPage model properties

Węzły najwyższego poziomu powiązane z modelem są weryfikowane jako uzupełnienie właściwości modelu.Model-bound top-level nodes are validated in addition to validating model properties. W poniższym przykładzie z przykładowej aplikacji VerifyPhone Metoda używa RegularExpressionAttribute do walidacji phone parametru Action:In the following example from the sample app, the VerifyPhone method uses the RegularExpressionAttribute to validate the phone action parameter:

[AcceptVerbs("Get", "Post")]
public IActionResult VerifyPhone(
    [RegularExpression(@"^\d{3}-\d{3}-\d{4}$")] string phone)
{
    if (!ModelState.IsValid)
    {
        return Json($"Phone {phone} has an invalid format. Format: ###-###-####");
    }

    return Json(true);
}

Węzły najwyższego poziomu mogą korzystać BindRequiredAttribute z atrybutów walidacji.Top-level nodes can use BindRequiredAttribute with validation attributes. W poniższym przykładzie z przykładowej aplikacji CheckAge Metoda określa, że age parametr musi być powiązany z ciągu zapytania, gdy formularz zostanie przesłany:In the following example from the sample app, the CheckAge method specifies that the age parameter must be bound from the query string when the form is submitted:

[HttpPost]
public IActionResult CheckAge(
    [BindRequired, FromQuery] int age)
{

Na stronie sprawdzanie wieku ( Sprawdź. cshtml ) Istnieją dwa formy.In the Check Age page ( CheckAge.cshtml ), there are two forms. Pierwszy formularz przesyła Age wartość 99 jako ciąg zapytania: https://localhost:5001/Users/CheckAge?Age=99 .The first form submits an Age value of 99 as a query string: https://localhost:5001/Users/CheckAge?Age=99.

Po przesłaniu poprawnie sformatowanego age parametru z ciągu zapytania, formularz sprawdza poprawność.When a properly formatted age parameter from the query string is submitted, the form validates.

Drugi formularz na stronie sprawdzanie wieku przesyła Age wartość w treści żądania, a Walidacja nie powiedzie się.The second form on the Check Age page submits the Age value in the body of the request, and validation fails. Powiązanie nie powiodło się, ponieważ age parametr musi pochodzić z ciągu zapytania.Binding fails because the age parameter must come from a query string.

W przypadku korzystania z programu CompatibilityVersion.Version_2_1 lub nowszego Walidacja węzła najwyższego poziomu jest domyślnie włączona.When running with CompatibilityVersion.Version_2_1 or later, top-level node validation is enabled by default. W przeciwnym razie Walidacja węzła najwyższego poziomu jest wyłączona.Otherwise, top-level node validation is disabled. Opcję domyślną można przesłonić AllowValidatingTopLevelNodes , ustawiając właściwość w ( Startup.ConfigureServices ), jak pokazano poniżej:The default option can be overridden by setting the AllowValidatingTopLevelNodes property in (Startup.ConfigureServices), as shown here:

services.AddMvc(options => 
    {
        options.MaxModelValidationErrors = 50;
        options.AllowValidatingTopLevelNodes = false;
    })
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Maksymalna liczba błędówMaximum errors

Walidacja jest zatrzymywana, gdy zostanie osiągnięta maksymalna liczba błędów (domyślnie 200).Validation stops when the maximum number of errors is reached (200 by default). Tę liczbę można skonfigurować przy użyciu następującego kodu w programie Startup.ConfigureServices :You can configure this number with the following code in Startup.ConfigureServices:

services.AddMvc(options => 
    {
        options.MaxModelValidationErrors = 50;
        options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
            (_) => "The field is required.");
    })
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton
    <IValidationAttributeAdapterProvider, 
     CustomValidationAttributeAdapterProvider>();

Maksymalna rekursjaMaximum recursion

ValidationVisitor przechodzi do grafu obiektów sprawdzanego przez model.ValidationVisitor traverses the object graph of the model being validated. W przypadku modeli, które są bardzo głębokie lub nieskończonie cykliczne, walidacja może spowodować przepełnienie stosu.For models that are very deep or are infinitely recursive, validation may result in stack overflow. MvcOptions. MaxValidationDepth umożliwia szybkie zakończenie sprawdzania poprawności, Jeśli rekursja odwiedzających przekracza skonfigurowaną głębokość.MvcOptions.MaxValidationDepth provides a way to stop validation early if the visitor recursion exceeds a configured depth. Wartość domyślna MvcOptions.MaxValidationDepth to 32 w przypadku uruchamiania z systemem CompatibilityVersion.Version_2_2 lub nowszym.The default value of MvcOptions.MaxValidationDepth is 32 when running with CompatibilityVersion.Version_2_2 or later. W przypadku wcześniejszych wersji wartość jest równa null, co oznacza brak ograniczenia głębokości.For earlier versions, the value is null, which means no depth constraint.

Automatyczny krótki obwódAutomatic short-circuit

Sprawdzanie poprawności jest automatycznie skracane (pomijane), jeśli wykres modelu nie wymaga weryfikacji.Validation is automatically short-circuited (skipped) if the model graph doesn't require validation. Obiekty, dla których środowisko uruchomieniowe pomija sprawdzanie poprawności dla dołączania kolekcji elementów podstawowych (takich jak byte[] , string[] , Dictionary<string, string> ) i złożonych wykresów obiektów, które nie mają żadnych modułów sprawdzania poprawności.Objects that the runtime skips validation for include collections of primitives (such as byte[], string[], Dictionary<string, string>) and complex object graphs that don't have any validators.

Wyłącz weryfikacjęDisable validation

Aby wyłączyć weryfikację:To disable validation:

  1. Utwórz implementację IObjectModelValidator , która nie oznacza żadnych pól jako nieprawidłowych.Create an implementation of IObjectModelValidator that doesn't mark any fields as invalid.

    public class NullObjectModelValidator : IObjectModelValidator
    {
        public void Validate(
            ActionContext actionContext,
            ValidationStateDictionary validationState,
            string prefix,
            object model)
        {
        }
    }
    
  2. Dodaj następujący kod, aby Startup.ConfigureServices zastąpić domyślną IObjectModelValidator implementację w kontenerze iniekcji zależności.Add the following code to Startup.ConfigureServices to replace the default IObjectModelValidator implementation in the dependency injection container.

    // There is only one `IObjectModelValidator` object,
    // so AddSingleton replaces the default one.
    services.AddSingleton<IObjectModelValidator>(new NullObjectModelValidator());
    

Nadal mogą pojawić się błędy stanu modelu pochodzące z powiązania modelu.You might still see model state errors that originate from model binding.

Weryfikacja po stronie klientaClient-side validation

Weryfikacja po stronie klienta uniemożliwia przesyłanie, dopóki formularz nie będzie prawidłowy.Client-side validation prevents submission until the form is valid. Przycisk Prześlij uruchamia kod JavaScript, który przesyła formularz lub wyświetla komunikaty o błędach.The Submit button runs JavaScript that either submits the form or displays error messages.

Weryfikacja po stronie klienta umożliwia uniknięcie niepotrzebnej komunikacji z serwerem w przypadku błędów danych wejściowych w formularzu.Client-side validation avoids an unnecessary round trip to the server when there are input errors on a form. Następujący skrypt odwołuje się do _Layout. cshtml i _ValidationScriptsPartial. cshtml obsługuje walidację po stronie klienta:The following script references in _Layout.cshtml and _ValidationScriptsPartial.cshtml support client-side validation:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

Skrypt niezauważalnego sprawdzania poprawności jQuery jest niestandardową biblioteką frontonu firmy Microsoft, która kompiluje się w popularnej wersji interfejsu jQuery .The jQuery Unobtrusive Validation script is a custom Microsoft front-end library that builds on the popular jQuery Validate plugin. Bez dyskretnej weryfikacji jQuery należy wykonać kod tej samej logiki walidacji w dwóch miejscach: raz w atrybuty walidacji po stronie serwera we właściwościach modelu, a następnie ponownie w skryptach po stronie klienta.Without jQuery Unobtrusive Validation, you would have to code the same validation logic in two places: once in the server-side validation attributes on model properties, and then again in client-side scripts. Zamiast tego, pomocników tagów i pomocników HTML używają atrybutów walidacji i metadanych typu z właściwości modelu do renderowania atrybutów HTML 5 data- dla elementów formularza, które wymagają walidacji.Instead, Tag Helpers and HTML helpers use the validation attributes and type metadata from model properties to render HTML 5 data- attributes for the form elements that need validation. niezauważalne sprawdzenie poprawności przez program jQuery umożliwia przeanalizowanie data- atrybutów i przekazanie logiki do programu jQuery Validate, efektywne "Kopiowanie" logiki walidacji po stronie serwera do klienta.jQuery Unobtrusive Validation parses the data- attributes and passes the logic to jQuery Validate, effectively "copying" the server-side validation logic to the client. Błędy sprawdzania poprawności można wyświetlić na kliencie przy użyciu pomocników tagów, jak pokazano poniżej:You can display validation errors on the client using tag helpers as shown here:

<div class="form-group">
    <label asp-for="ReleaseDate" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="ReleaseDate" class="form-control" />
        <span asp-validation-for="ReleaseDate" class="text-danger"></span>
    </div>
</div>

Poprzednie pomocnicy tagów renderują następujący kod HTML.The preceding tag helpers render the following HTML.

<form action="/Movies/Create" method="post">
    <div class="form-horizontal">
        <h4>Movie</h4>
        <div class="text-danger"></div>
        <div class="form-group">
            <label class="col-md-2 control-label" for="ReleaseDate">ReleaseDate</label>
            <div class="col-md-10">
                <input class="form-control" type="datetime"
                data-val="true" data-val-required="The ReleaseDate field is required."
                id="ReleaseDate" name="ReleaseDate" value="">
                <span class="text-danger field-validation-valid"
                data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
            </div>
        </div>
    </div>
</form>

Zauważ, że data- atrybuty w danych wyjściowych HTML odpowiadają atrybutom walidacji ReleaseDate właściwości.Notice that the data- attributes in the HTML output correspond to the validation attributes for the ReleaseDate property. Ten data-val-required atrybut zawiera komunikat o błędzie, który zostanie wyświetlony, jeśli użytkownik nie wypełni pola Data wydania.The data-val-required attribute contains an error message to display if the user doesn't fill in the release date field. niezauważalne sprawdzenie poprawności przez funkcję jQuery powoduje, że ta wartość jest przekazywana do walidacji wymaganej metody () , która następnie wyświetla ten komunikat w elemencie towarzyszącym <span> .jQuery Unobtrusive Validation passes this value to the jQuery Validate required() method, which then displays that message in the accompanying <span> element.

Walidacja typu danych jest oparta na typie .NET właściwości, chyba że zostanie zastąpiona przez [DataType] atrybut.Data type validation is based on the .NET type of a property, unless that is overridden by a [DataType] attribute. Przeglądarki mają własne domyślne komunikaty o błędach, ale pakietem weryfikacji jQuery nie dyskretnego sprawdzania poprawności może przesłonić te komunikaty.Browsers have their own default error messages, but the jQuery Validation Unobtrusive Validation package can override those messages. [DataType] atrybuty i podklasy, takie jak [EmailAddress] pozwalają określić komunikat o błędzie.[DataType] attributes and subclasses such as [EmailAddress] let you specify the error message.

Dodawanie walidacji do formularzy dynamicznychAdd Validation to Dynamic Forms

w przypadku niedyskretnego sprawdzania poprawności jest sprawdzana logika walidacji i parametry do jQuery podczas pierwszego ładowania strony.jQuery Unobtrusive Validation passes validation logic and parameters to jQuery Validate when the page first loads. W związku z tym sprawdzanie poprawności nie działa automatycznie na formularzach generowanych dynamicznie.Therefore, validation doesn't work automatically on dynamically generated forms. Aby włączyć weryfikację, poinformuj jQuery o niezauważalnej weryfikacji, aby przeanalizować formularz dynamiczny bezpośrednio po jego utworzeniu.To enable validation, tell jQuery Unobtrusive Validation to parse the dynamic form immediately after you create it. Na przykład poniższy kod konfiguruje walidację po stronie klienta w formularzu dodanym przez AJAX.For example, the following code sets up client-side validation on a form added via AJAX.

$.get({
    url: "https://url/that/returns/a/form",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add form. " + errorThrown);
    },
    success: function(newFormHTML) {
        var container = document.getElementById("form-container");
        container.insertAdjacentHTML("beforeend", newFormHTML);
        var forms = container.getElementsByTagName("form");
        var newForm = forms[forms.length - 1];
        $.validator.unobtrusive.parse(newForm);
    }
})

$.validator.unobtrusive.parse()Metoda akceptuje selektor jQuery dla jednego argumentu.The $.validator.unobtrusive.parse() method accepts a jQuery selector for its one argument. Ta metoda informuje niedyskretną weryfikację jQuery do analizy data- atrybutów formularzy w ramach tego selektora.This method tells jQuery Unobtrusive Validation to parse the data- attributes of forms within that selector. Wartości tych atrybutów są następnie przesyłane do wtyczki do walidacji jQuery.The values of those attributes are then passed to the jQuery Validate plugin.

Dodawanie walidacji do formantów dynamicznychAdd Validation to Dynamic Controls

$.validator.unobtrusive.parse()Metoda działa na całym formularzu, a nie na poszczególnych dynamicznie generowanych kontrolkach, takich jak <input> i <select/> .The $.validator.unobtrusive.parse() method works on an entire form, not on individual dynamically generated controls, such as <input> and <select/>. Aby przeanalizować formularz, Usuń dane sprawdzania poprawności, które zostały dodane, gdy formularz został wcześniej przeanalizowany, jak pokazano w następującym przykładzie:To reparse the form, remove the validation data that was added when the form was parsed earlier, as shown in the following example:

$.get({
    url: "https://url/that/returns/a/control",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add control. " + errorThrown);
    },
    success: function(newInputHTML) {
        var form = document.getElementById("my-form");
        form.insertAdjacentHTML("beforeend", newInputHTML);
        $(form).removeData("validator")    // Added by jQuery Validate
               .removeData("unobtrusiveValidation");   // Added by jQuery Unobtrusive Validation
        $.validator.unobtrusive.parse(form);
    }
})

Niestandardowe sprawdzanie poprawności po stronie klientaCustom client-side validation

Niestandardowe sprawdzanie poprawności po stronie klienta jest wykonywane przez generowanie data- atrybutów HTML, które działają z niestandardowym identyfikatorem platformy jQuery.Custom client-side validation is done by generating data- HTML attributes that work with a custom jQuery Validate adapter. Następujący przykładowy kod karty został zapisany dla ClassicMovie ClassicMovie2 atrybutów i, które zostały wprowadzone wcześniej w tym artykule:The following sample adapter code was written for the ClassicMovie and ClassicMovie2 attributes that were introduced earlier in this article:

$.validator.addMethod('classicmovie',
    function (value, element, params) {
        // Get element value. Classic genre has value '0'.
        var genre = $(params[0]).val(),
            year = params[1],
            date = new Date(value);
        if (genre && genre.length > 0 && genre[0] === '0') {
            // Since this is a classic movie, invalid if release date is after given year.
            return date.getUTCFullYear() <= year;
        }

        return true;
    });

$.validator.unobtrusive.adapters.add('classicmovie',
    ['year'],
    function (options) {
        var element = $(options.form).find('select#Genre')[0];
        options.rules['classicmovie'] = [element, parseInt(options.params['year'])];
        options.messages['classicmovie'] = options.message;
    });

Aby uzyskać informacje o sposobach pisania kart sieciowych, zobacz dokumentację dotyczącą platformy jQuery Validate.For information about how to write adapters, see the jQuery Validate documentation.

Użycie karty dla danego pola jest wyzwalane przez data- atrybuty, które:The use of an adapter for a given field is triggered by data- attributes that:

  • Oznacz pole jako podlegające walidacji ( data-val="true" ).Flag the field as being subject to validation (data-val="true").
  • Zidentyfikuj nazwę reguły walidacji i tekst komunikatu o błędzie (na przykład data-val-rulename="Error message." ).Identify a validation rule name and error message text (for example, data-val-rulename="Error message.").
  • Podaj wszelkie dodatkowe parametry wymagane przez moduł sprawdzania poprawności (na przykład data-val-rulename-parm1="value" ).Provide any additional parameters the validator needs (for example, data-val-rulename-parm1="value").

W poniższym przykładzie przedstawiono data- atrybuty dla atrybutu przykładowej aplikacji ClassicMovie :The following example shows the data- attributes for the sample app's ClassicMovie attribute:

<input class="form-control" type="datetime"
    data-val="true"
    data-val-classicmovie1="Classic movies must have a release year earlier than 1960."
    data-val-classicmovie1-year="1960"
    data-val-required="The ReleaseDate field is required."
    id="ReleaseDate" name="ReleaseDate" value="">

Jak wspomniano wcześniej, pomocników tagów i pomocników HTML wykorzystują informacje z atrybutów walidacji do renderowania data- atrybutów.As noted earlier, Tag Helpers and HTML helpers use information from validation attributes to render data- attributes. Istnieją dwie opcje pisania kodu, które powoduje tworzenie niestandardowych data- atrybutów HTML:There are two options for writing code that results in the creation of custom data- HTML attributes:

  • Utwórz klasę, która pochodzi od AttributeAdapterBase<TAttribute> i klasy implementującej IValidationAttributeAdapterProvider , i Zarejestruj swój atrybut oraz jego kartę w programie di.Create a class that derives from AttributeAdapterBase<TAttribute> and a class that implements IValidationAttributeAdapterProvider, and register your attribute and its adapter in DI. Ta metoda jest zgodna z pojedynczym podmiotem odpowiedzialnym w odniesieniu do kodu weryfikacyjnego związanego z serwerem i klienta jest w osobnych klasach.This method follows the single responsibility principal in that server-related and client-related validation code is in separate classes. Adapter ma również zalety, że ponieważ jest on zarejestrowany w programie DI, w razie potrzeby są dostępne inne usługi w programie DI.The adapter also has the advantage that since it is registered in DI, other services in DI are available to it if needed.
  • Zaimplementuj IClientModelValidator w ValidationAttribute klasie.Implement IClientModelValidator in your ValidationAttribute class. Ta metoda może być odpowiednia, jeśli atrybut nie wykonuje walidacji po stronie serwera i nie wymaga żadnych usług z programu DI.This method might be appropriate if the attribute doesn't do any server-side validation and doesn't need any services from DI.

AttributeAdapter dla weryfikacji po stronie klientaAttributeAdapter for client-side validation

Ta metoda renderowania data- atrybutów w kodzie HTML jest używana przez ClassicMovie atrybut w przykładowej aplikacji.This method of rendering data- attributes in HTML is used by the ClassicMovie attribute in the sample app. Aby dodać weryfikację klienta przy użyciu tej metody:To add client validation by using this method:

  1. Utwórz klasę adaptera atrybutów dla niestandardowego atrybutu walidacji.Create an attribute adapter class for the custom validation attribute. Utwórz klasę z AttributeAdapterBase <T> .Derive the class from AttributeAdapterBase<T>. Utwórz AddValidation metodę, która dodaje data- atrybuty do renderowanych danych wyjściowych, jak pokazano w tym przykładzie:Create an AddValidation method that adds data- attributes to the rendered output, as shown in this example:

    public class ClassicMovieAttributeAdapter : AttributeAdapterBase<ClassicMovieAttribute>
    {
        private int _year;
    
        public ClassicMovieAttributeAdapter(ClassicMovieAttribute attribute, IStringLocalizer stringLocalizer) : base (attribute, stringLocalizer)
        {
            _year = attribute.Year;
        }
        public override void AddValidation(ClientModelValidationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage(context));
    
            var year = Attribute.Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
        public override string GetErrorMessage(ModelValidationContextBase validationContext)
        {
            return Attribute.GetErrorMessage();
        }
    }
    
  2. Utwórz klasę dostawcy kart implementującą IValidationAttributeAdapterProvider .Create an adapter provider class that implements IValidationAttributeAdapterProvider. W GetAttributeAdapter metodzie Przekaż atrybut niestandardowy do konstruktora adaptera, jak pokazano w tym przykładzie:In the GetAttributeAdapter method pass in the custom attribute to the adapter's constructor, as shown in this example:

    public class CustomValidationAttributeAdapterProvider :
        IValidationAttributeAdapterProvider
    {
        IValidationAttributeAdapterProvider baseProvider =
            new ValidationAttributeAdapterProvider();
        public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute,
            IStringLocalizer stringLocalizer)
        {
            if (attribute is ClassicMovieAttribute classicMovieAttribute)
            {
                return new ClassicMovieAttributeAdapter(classicMovieAttribute, stringLocalizer);
            }
            else
            {
                return baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
            }
        }
    }
    
  3. Zarejestruj dostawcę karty dla DI in Startup.ConfigureServices :Register the adapter provider for DI in Startup.ConfigureServices:

    services.AddMvc(options => 
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                (_) => "The field is required.");
        })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddSingleton
        <IValidationAttributeAdapterProvider, 
         CustomValidationAttributeAdapterProvider>();
    

IClientModelValidator dla weryfikacji po stronie klientaIClientModelValidator for client-side validation

Ta metoda renderowania data- atrybutów w kodzie HTML jest używana przez ClassicMovie2 atrybut w przykładowej aplikacji.This method of rendering data- attributes in HTML is used by the ClassicMovie2 attribute in the sample app. Aby dodać weryfikację klienta przy użyciu tej metody:To add client validation by using this method:

  • W atrybucie niestandardowego sprawdzania poprawności Zaimplementuj IClientModelValidator interfejs i Utwórz AddValidation metodę.In the custom validation attribute, implement the IClientModelValidator interface and create an AddValidation method. W AddValidation metodzie Dodaj data- atrybuty do walidacji, jak pokazano w następującym przykładzie:In the AddValidation method, add data- attributes for validation, as shown in the following example:

    
    public class ClassicMovie2Attribute : ValidationAttribute, IClientModelValidator
    {
        private int _year;
    
        public ClassicMovie2Attribute(int year)
        {
            _year = year;
        }
    
        protected override ValidationResult IsValid(
            object value, ValidationContext validationContext)
        {
            var movie = (Movie)validationContext.ObjectInstance;
            var releaseYear = ((DateTime)value).Year;
    
            if (movie.Genre == Genre.Classic && releaseYear > _year)
            {
                return new ValidationResult(GetErrorMessage());
            }
    
            return ValidationResult.Success;
        }
    
        public void AddValidation(ClientModelValidationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());
    
            var year = _year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
        private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (attributes.ContainsKey(key))
            {
                return false;
            }
    
            attributes.Add(key, value);
            return true;
        }
        protected string GetErrorMessage()
        {
            return $"Classic movies must have a release year no later than {_year} [from attribute 2].";
        }
    }
    

Wyłącz weryfikację po stronie klientaDisable client-side validation

Poniższy kod wyłącza weryfikację klienta w widokach MVC:The following code disables client validation in MVC views:

services.AddMvc().AddViewOptions(options =>
{
    if (_env.IsDevelopment())
    {
        options.HtmlHelperOptions.ClientValidationEnabled = false;
    }
});

I na Razor stronach:And in Razor Pages:

services.Configure<HtmlHelperOptions>(o => o.ClientValidationEnabled = false);

Kolejną opcją wyłączenia sprawdzania poprawności klienta jest komentarz do odwołania do _ValidationScriptsPartial w pliku . cshtml .Another option for disabling client validation is to comment out the reference to _ValidationScriptsPartial in your .cshtml file.

Dodatkowe zasobyAdditional resources