Convalida del modello in ASP.NET Core MVC e in Razor PagesModel validation in ASP.NET Core MVC and Razor Pages

Di Kirk LarkinBy Kirk Larkin

Questo articolo illustra come convalidare l'input utente in un'app ASP.NET Core MVC o Razor Pages.This article explains how to validate user input in an ASP.NET Core MVC or Razor Pages app.

Visualizzare o scaricare il codice di esempio (procedura per il download).View or download sample code (how to download).

Stato del modelloModel state

Lo stato del modello rappresenta gli errori che provengono da due sottosistemi: associazione di modelli e convalida del modello.Model state represents errors that come from two subsystems: model binding and model validation. Gli errori originati dall' associazione di modelli sono in genere errori di conversione dei dati.Errors that originate from model binding are generally data conversion errors. Ad esempio, una "x" viene immessa in un campo integer.For example, an "x" is entered in an integer field. La convalida del modello avviene dopo l'associazione di modelli e segnala gli errori in cui i dati non sono conformi alle regole businessModel validation occurs after model binding and reports errors where data doesn't conform to business rules. Ad esempio, un valore 0 viene immesso in un campo che prevede una classificazione compresa tra 1 e 5.For example, a 0 is entered in a field that expects a rating between 1 and 5.

L'associazione di modelli e la convalida del modello si verificano prima dell'esecuzione di un'azione del controller o di un metodo del gestore Razor Pages.Both model binding and model validation occur before the execution of a controller action or a Razor Pages handler method. Per le app Web, è responsabilità dell'app esaminare ModelState.IsValid e rispondere nel modo appropriato.For web apps, it's the app's responsibility to inspect ModelState.IsValid and react appropriately. Le app Web in genere visualizzare di nuovo la pagina con un messaggio di errore: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");
}

I controller API Web non devono controllare ModelState.IsValid se hanno l'attributo [ApiController].Web API controllers don't have to check ModelState.IsValid if they have the [ApiController] attribute. In tal caso, viene restituita una risposta HTTP 400 automatica contenente i dettagli dell'errore quando lo stato del modello non è valido.In that case, an automatic HTTP 400 response containing error details is returned when model state is invalid. Per altre informazioni, vedere Risposte HTTP 400 automatiche.For more information, see Automatic HTTP 400 responses.

Rieseguire la convalidaRerun validation

La convalida è automatica, ma potrebbe essere necessario ripeterla manualmente.Validation is automatic, but you might want to repeat it manually. Ad esempio, è possibile che si calcoli un valore per una proprietà e che si voglia rieseguire la convalida dopo aver impostato la proprietà sul valore calcolato.For example, you might compute a value for a property and want to rerun validation after setting the property to the computed value. Per rieseguire la convalida, chiamare il metodo TryValidateModel come illustrato di seguito: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");

Attributi di convalidaValidation attributes

Gli attributi di convalida consentono di specificare le regole di convalida per le proprietà del modello.Validation attributes let you specify validation rules for model properties. Nell'esempio seguente dall'app di esempio viene illustrata una classe di modello che viene annotata con gli attributi di convalida.The following example from the sample app shows a model class that is annotated with validation attributes. [ClassicMovie] è un attributo di convalida personalizzato, mentre gli altri sono attributi predefiniti.The [ClassicMovie] attribute is a custom validation attribute and the others are built-in. Non viene visualizzato [ClassicMovieWithClientValidator].Not shown is [ClassicMovieWithClientValidator]. [ClassicMovieWithClientValidator] Mostra un metodo alternativo per implementare un attributo personalizzato.[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; }
}

Attributi predefinitiBuilt-in attributes

Di seguito sono elencati alcuni degli attributi di convalida predefiniti:Here are some of the built-in validation attributes:

  • [CreditCard]: convalida che la proprietà abbia un formato di carta di credito.[CreditCard]: Validates that the property has a credit card format.
  • [Compare]: verifica che due proprietà di un modello corrispondano.[Compare]: Validates that two properties in a model match.
  • [EmailAddress]: convalida che la proprietà abbia un formato di posta elettronica.[EmailAddress]: Validates that the property has an email format.
  • [Phone]: convalida che la proprietà abbia un formato di numero di telefono.[Phone]: Validates that the property has a telephone number format.
  • [Range]: verifica che il valore della proprietà sia compreso in un intervallo specificato.[Range]: Validates that the property value falls within a specified range.
  • [RegularExpression]: verifica che il valore della proprietà corrisponda a un'espressione regolare specificata.[RegularExpression]: Validates that the property value matches a specified regular expression.
  • [Required]: verifica che il campo non sia null.[Required]: Validates that the field is not null. Vedere l'attributo [Required] per informazioni dettagliate sul comportamento di questo attributo.See [Required] attribute for details about this attribute's behavior.
  • [StringLength]: verifica che un valore della proprietà stringa non superi il limite di lunghezza specificato.[StringLength]: Validates that a string property value doesn't exceed a specified length limit.
  • [Url]: convalida che la proprietà abbia un formato URL.[Url]: Validates that the property has a URL format.
  • [Remote]: convalida l'input sul client chiamando un metodo di azione sul server.[Remote]: Validates input on the client by calling an action method on the server. Vedere l'attributo [Remote] per informazioni dettagliate sul comportamento di questo attributo.See [Remote] attribute for details about this attribute's behavior.

Nello spazio dei nomi System.ComponentModel.DataAnnotations è possibile trovare un elenco completo degli attributi di convalida.A complete list of validation attributes can be found in the System.ComponentModel.DataAnnotations namespace.

Messaggi di erroreError messages

Gli attributi di convalida consentono di specificare il messaggio di errore da visualizzare in caso di input non valido.Validation attributes let you specify the error message to be displayed for invalid input. Ad esempio:For example:

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

Internamente gli attributi chiamano String.Format con un segnaposto per il nome campo e talvolta con segnaposto aggiuntivi.Internally, the attributes call String.Format with a placeholder for the field name and sometimes additional placeholders. Ad esempio:For example:

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

Quando applicato a una proprietà Name, il messaggio di errore creato con il codice precedente sarà "La lunghezza del nome utente deve essere compresa tra 6 e 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.".

Per scoprire i parametri passati a String.Format per un messaggio di errore dell'attributo specifico, vedere il codice sorgente DataAnnotations.To find out which parameters are passed to String.Format for a particular attribute's error message, see the DataAnnotations source code.

Attributo [Required][Required] attribute

Per impostazione predefinita, il sistema di convalida considera i parametri non nullable o le proprietà come se avessero un attributo [Required].By default, the validation system treats non-nullable parameters or properties as if they had a [Required] attribute. I tipi di valore decimal e int sono parametri non nullable.Value types such as decimal and int are non-nullable.

Convalida dell'attributo [Required] nel server[Required] validation on the server

Nel server un valore obbligatorio viene considerato mancante se la proprietà è Null.On the server, a required value is considered missing if the property is null. Un campo che non ammette i valori null è sempre valido e il messaggio di errore dell'attributo [Required] non viene mai visualizzato.A non-nullable field is always valid, and the [Required] attribute's error message is never displayed.

Può però succedere che l'associazione di modelli per una proprietà non nullable abbia esito negativo, generando un messaggio di errore, ad esempio 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. Per specificare un messaggio di errore personalizzato per la convalida lato server di tipi non nullable, sono disponibili le opzioni seguenti:To specify a custom error message for server-side validation of non-nullable types, you have the following options:

  • Il campo deve ammettere i valori Null, ad esempio decimal? anziché decimal.Make the field nullable (for example, decimal? instead of decimal). I tipi di valore Nullable<T> vengono considerati tipi nullable standard.Nullable<T> value types are treated like standard nullable types.

  • Specificare il messaggio di errore predefinito che l'associazione di modelli deve usare, come illustrato nell'esempio seguente: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>();
    

    Per altre informazioni sugli errori dell'associazione di modelli che possono essere impostati come messaggi predefiniti, vedere DefaultModelBindingMessageProvider.For more information about model binding errors that you can set default messages for, see DefaultModelBindingMessageProvider.

Convalida dell'attributo [Required] nel client[Required] validation on the client

Le stringhe e i tipi non nullable sono gestiti in modo diverso nel client rispetto a come vengono gestiti nel server.Non-nullable types and strings are handled differently on the client compared to the server. Nel client:On the client:

  • Un valore viene considerato presente solo viene immesso un input per tale valore.A value is considered present only if input is entered for it. La convalida lato client gestisce quindi i tipi non nullable come i tipi nullable.Therefore, client-side validation handles non-nullable types the same as nullable types.
  • Lo spazio vuoto in un campo stringa viene considerato un input valido per il metodo required della convalida di jQuery.Whitespace in a string field is considered valid input by the jQuery Validation required method. La convalida lato server considera un campo stringa obbligatorio non valido solo se viene immesso uno spazio vuoto.Server-side validation considers a required string field invalid if only whitespace is entered.

Come indicato in precedenza, i tipi non nullable vengono trattati come se avessero un attributo [Required].As noted earlier, non-nullable types are treated as though they had a [Required] attribute. Quindi viene eseguita la convalida lato client anche se non si applica l'attributo [Required].That means you get client-side validation even if you don't apply the [Required] attribute. Se invece non si usa l'attributo, viene visualizzato un messaggio di errore predefinito.But if you don't use the attribute, you get a default error message. Per specificare un messaggio di errore personalizzato, usare l'attributo.To specify a custom error message, use the attribute.

Attributo [Remote][Remote] attribute

L'attributo [Remote] implementa la convalida lato client che richiede la chiamata a un metodo nel server per determinare se l'input del campo è valido.The [Remote] attribute implements client-side validation that requires calling a method on the server to determine whether field input is valid. Ad esempio, l'app potrebbe dover verificare se un nome utente è già in uso.For example, the app may need to verify whether a user name is already in use.

Per implementare la convalida remota:To implement remote validation:

  1. Creare un metodo di azione per JavaScript da chiamare.Create an action method for JavaScript to call. Il metodo remote jQuery Validate prevede una risposta JSON:The jQuery Validate remote method expects a JSON response:

    • true indica che i dati di input sono validi.true means the input data is valid.
    • false, undefined o null indica che l'input non è valido.false, undefined, or null means the input is invalid. Visualizzare il messaggio di errore predefinito.Display the default error message.
    • Qualsiasi altra stringa indica che l'input non è valido.Any other string means the input is invalid. Visualizzare la stringa come messaggio di errore personalizzato.Display the string as a custom error message.

    Di seguito è riportato un esempio di un metodo di azione che restituisce un messaggio di errore personalizzato: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. Nella classe del modello annotare la proprietà con un attributo [Remote] che punta al metodo di azione di convalida, come illustrato nell'esempio seguente: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; }
    

    L'attributo [Remote] si trova nello spazio dei nomi Microsoft.AspNetCore.Mvc.The [Remote] attribute is in the Microsoft.AspNetCore.Mvc namespace.

Campi aggiuntiviAdditional fields

La proprietà AdditionalFields dell'attributo [Remote] consente di convalidare combinazioni di campi rispetto ai dati nel server.The AdditionalFields property of the [Remote] attribute lets you validate combinations of fields against data on the server. Ad esempio, se il modello User avesse le proprietà FirstName e LastName, potrebbe essere necessario controllare che non siano già esistenti utenti con la stessa coppia di nomi.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. Nell'esempio riportato di seguito viene illustrato come usare 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; }

È stato possibile impostare in modo esplicito AdditionalFields sulle stringhe "FirstName" e "LastName", ma usando l'operatore nameof il successivo refactoring risulta semplificato.AdditionalFields could be set explicitly to the strings "FirstName" and "LastName", but using the nameof operator simplifies later refactoring. Il metodo di azione per questa convalida deve accettare sia firstName che lastName argomenti: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);
}

Quando si immette un nome o un cognome, JavaScript esegue una chiamata remota per verificare se tale coppia di nomi è in uso.When the user enters a first or last name, JavaScript makes a remote call to see if that pair of names has been taken.

Per convalidare due o più campi aggiuntivi, specificarli sotto forma di elenco delimitato da virgole.To validate two or more additional fields, provide them as a comma-delimited list. Ad esempio, per aggiungere una proprietà MiddleName al modello, impostare l'attributo [Remote] come illustrato nell'esempio seguente: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, come tutti gli argomenti dell'attributo, deve essere un'espressione costante.AdditionalFields, like all attribute arguments, must be a constant expression. Non usare quindi una stringa interpolata oppure chiamare Join per inizializzare AdditionalFields.Therefore, don't use an interpolated string or call Join to initialize AdditionalFields.

Alternative agli attributi predefinitiAlternatives to built-in attributes

Se si vuole usare un tipo di convalida non definita da attributi predefiniti, è possibile eseguire le operazioni seguenti:If you need validation not provided by built-in attributes, you can:

Attributi personalizzatiCustom attributes

Per gli scenari non gestiti dagli attributi di convalida predefiniti, è possibile creare attributi di convalida personalizzati.For scenarios that the built-in validation attributes don't handle, you can create custom validation attributes. Creare una classe che eredita da ValidationAttribute ed eseguire l'override del metodo IsValid.Create a class that inherits from ValidationAttribute, and override the IsValid method.

Il metodo IsValid accetta un oggetto denominato value, ovvero l'input da convalidare.The IsValid method accepts an object named value, which is the input to be validated. Un overload accetta anche un oggetto ValidationContext, che contiene informazioni aggiuntive, ad esempio l'istanza del modello creato dall'associazione di modelli.An overload also accepts a ValidationContext object, which provides additional information, such as the model instance created by model binding.

Nell'esempio seguente si convalida che la data di uscita di un film di genere Classic non sia successiva a un anno specifico.The following example validates that the release date for a movie in the Classic genre isn't later than a specified year. Attributo [ClassicMovie]:The [ClassicMovie] attribute:

  • Viene eseguito solo sul server.Is only run on the server.
  • Per i filmati classici, convalida la data di rilascio: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;
    }
}

La variabile movie nell'esempio precedente rappresenta un oggetto Movie contenente i dati dell'invio del modulo.The movie variable in the preceding example represents a Movie object that contains the data from the form submission. Se la convalida ha esito negativo, viene restituito un codice ValidationResult con un messaggio di errore.When validation fails, a ValidationResult with an error message is returned.

IValidatableObjectIValidatableObject

L'esempio precedente usa solo tipi Movie.The preceding example works only with Movie types. Un'altra opzione per la convalida a livello di classe consiste nell'implementare IValidatableObject nella classe del modello, come illustrato nell'esempio seguente: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) });
        }
    }
}

Convalida del nodo di primo livelloTop-level node validation

I nodi di primo livello includono:Top-level nodes include:

  • Parametri di azioneAction parameters
  • Proprietà del controllerController properties
  • Parametri del gestore di paginaPage handler parameters
  • Proprietà del modello di paginaPage model properties

Vengono convalidati i nodi di primo livello associati al modello, oltre a convalidare le proprietà del modello.Model-bound top-level nodes are validated in addition to validating model properties. Nell'esempio seguente dell'app di esempio il metodo VerifyPhone usa RegularExpressionAttribute per convalidare il parametro di azione phone: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);
}

I nodi di primo livello possono usare BindRequiredAttribute con gli attributi di convalida.Top-level nodes can use BindRequiredAttribute with validation attributes. Nell'esempio seguente dall'app di esempio, il metodo CheckAge specifica che il parametro age deve essere associato dalla stringa di query quando viene inviato il modulo: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)
{

La pagina Check Age (CheckAge.cshtml), include due moduli.In the Check Age page (CheckAge.cshtml), there are two forms. Il primo form invia un valore Age di 99 come parametro della stringa di query: 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.

Quando viene inviato un parametro correttamente formattato age dalla stringa di query, il modulo viene convalidato.When a properly formatted age parameter from the query string is submitted, the form validates.

Il secondo modulo nella pagina Check Age invia il valore Age nel corpo della richiesta e la convalida ha esito negativo.The second form on the Check Age page submits the Age value in the body of the request, and validation fails. L'associazione non riesce perché il parametro age deve provenire da una stringa di query.Binding fails because the age parameter must come from a query string.

Numero massimo di erroriMaximum errors

La convalida si interrompe quando viene raggiunto il numero di errori (200 per impostazione predefinita).Validation stops when the maximum number of errors is reached (200 by default). È possibile configurare questo numero con il codice seguente in 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>();

Numero massimo di ricorsioniMaximum recursion

ValidationVisitor attraversare l'oggetto grafico del modello che deve essere convalidato.ValidationVisitor traverses the object graph of the model being validated. Per i modelli che sono profondi o sono infinitamente ricorsivi, la convalida può causare un overflow dello stack.For models that are deep or are infinitely recursive, validation may result in stack overflow. MvcOptions.MaxValidationDepth consente di arrestare tempestivamente la convalida se la ricorsione del visitatore supera la profondità configurata.MvcOptions.MaxValidationDepth provides a way to stop validation early if the visitor recursion exceeds a configured depth. Il valore predefinito di MvcOptions.MaxValidationDepth è 32.The default value of MvcOptions.MaxValidationDepth is 32.

Corto circuito automaticoAutomatic short-circuit

La convalida viene ignorata automaticamente (corto circuito) se l'oggetto grafico non richiede la convalida.Validation is automatically short-circuited (skipped) if the model graph doesn't require validation. Gli oggetti per cui viene ignorata la convalida sono le raccolte di primitive (ad esempio byte[], string[], Dictionary<string, string>) e gli oggetti grafici complessi che non hanno validator.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.

Disabilitare la convalidaDisable validation

Per disabilitare la convalida:To disable validation:

  1. Creare un'implementazione di IObjectModelValidator che non contrassegna i campi come non validi.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. Aggiungere il codice seguente a Startup.ConfigureServices per sostituire l'impostazione IObjectModelValidator predefinita nel contenitore di inserimento delle dipendenze.Add the following code to Startup.ConfigureServices to replace the default IObjectModelValidator implementation in the dependency injection container.

    services.AddSingleton<IObjectModelValidator, NullObjectModelValidator>();
    

Potrebbero essere visualizzati errori di stato del modello generati dall'associazione di modelli.You might still see model state errors that originate from model binding.

Convalida lato clientClient-side validation

La convalida lato client non consente l'invio del modulo finché non è ritenuto valido.Client-side validation prevents submission until the form is valid. Tramite il pulsante Invia viene eseguito JavaScript, che invia il modulo oppure visualizza i messaggi di errore.The Submit button runs JavaScript that either submits the form or displays error messages.

La convalida lato client evitare un inutile round trip al server in caso di errori di input in un modulo.Client-side validation avoids an unnecessary round trip to the server when there are input errors on a form. I riferimenti dello script seguenti in _Layout.cshtml e _ValidationScriptsPartial.cshtml supportano la convalida lato client: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>

Lo script jQuery Unobtrusive Validation è una libreria front-end Microsoft personalizzata che si basa sul noto plug-in jQuery Validate.The jQuery Unobtrusive Validation script is a custom Microsoft front-end library that builds on the popular jQuery Validate plugin. Senza Query Unobtrusive Validation, sarebbe necessario scrivere il codice della stessa logica di convalida in due posizioni, vale a dire negli attributi di convalida lato server nelle proprietà del modello e nuovamente negli script lato client.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. Invece, gli helper tage agli helper HTML usano gli attributi di convalida e i metadati di tipo delle proprietà del modello per eseguire il rendering degli attributi data- HTML 5 negli elementi del modulo che devono essere convalidati.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. jQuery Unobtrusive Validation analizza gli attributi data- e passa la logica a jQuery Validate, "copiando" in modo efficace la logica di convalida lato server nel client.jQuery Unobtrusive Validation parses the data- attributes and passes the logic to jQuery Validate, effectively "copying" the server-side validation logic to the client. È possibile visualizzare gli errori di convalida nel client tramite gli helper tag, come illustrato di seguito: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>

Gli helper tag precedenti eseguono il rendering del codice HTML seguente: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>

Si noti che gli attributi data- nell'output HTML corrispondono agli attributi di convalida per la proprietà Movie.ReleaseDate.Notice that the data- attributes in the HTML output correspond to the validation attributes for the Movie.ReleaseDate property. L'attributo data-val-required contiene un messaggio di errore che viene visualizzato se l'utente non compila il campo relativo alla data di uscita.The data-val-required attribute contains an error message to display if the user doesn't fill in the release date field. Lo script jQuery Unobtrusive Validation passa questo valore al metodo required() jQuery Validate, che visualizza il messaggio nell'elemento <span> di accompagnamento.jQuery Unobtrusive Validation passes this value to the jQuery Validate required() method, which then displays that message in the accompanying <span> element.

La convalida del tipo di dati si basa sul tipo .NET di una proprietà, a meno che sia sostituito dall'attributo [DataType].Data type validation is based on the .NET type of a property, unless that is overridden by a [DataType] attribute. I browser generano messaggi di errore predefiniti propri che il pacchetto jQuery Validation Unobtrusive Validation può comunque sostituire.Browsers have their own default error messages, but the jQuery Validation Unobtrusive Validation package can override those messages. Gli attributi [DataType] e le sottoclassi, ad esempio [EmailAddress], consentono di specificare il messaggio di errore.[DataType] attributes and subclasses such as [EmailAddress] let you specify the error message.

Aggiungere la convalida a moduli dinamiciAdd Validation to Dynamic Forms

Quando la pagina viene caricata, jQuery Unobtrusive Validation passa la logica e i parametri di convalida a jQuery Validate.jQuery Unobtrusive Validation passes validation logic and parameters to jQuery Validate when the page first loads. La convalida non viene quindi eseguita automaticamente nei moduli generati in modo dinamico.Therefore, validation doesn't work automatically on dynamically generated forms. Per abilitare la convalida, chiedere a jQuery Unobtrusive Validation di analizzare il modulo dinamico immediatamente dopo essere stato creato.To enable validation, tell jQuery Unobtrusive Validation to parse the dynamic form immediately after you create it. Il codice riportato di seguito configura ad esempio la convalida lato client in un modulo che è stato aggiunto tramite 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);
    }
})

Il metodo $.validator.unobtrusive.parse() accetta un selettore jQuery per ogni argomento.The $.validator.unobtrusive.parse() method accepts a jQuery selector for its one argument. Questo metodo indica a jQuery Unobtrusive Validation di analizzare gli attributi data- dei moduli all'interno di tale tipo di selettore.This method tells jQuery Unobtrusive Validation to parse the data- attributes of forms within that selector. I valori di tali attributi vengono quindi passati al plug-in jQuery Validate.The values of those attributes are then passed to the jQuery Validate plugin.

Aggiungere la convalida a controlli dinamiciAdd Validation to Dynamic Controls

Il metodo $.validator.unobtrusive.parse() funziona su un intero modulo e non sui singoli controlli generati dinamicamente, ad esempio <input> e <select/>.The $.validator.unobtrusive.parse() method works on an entire form, not on individual dynamically generated controls, such as <input> and <select/>. Per eseguire il reparse del modulo, rimuovere i dati di convalida aggiunti quando il modulo è stato precedentemente analizzato, come illustrato nell'esempio seguente: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);
    }
})

Convalida lato client personalizzataCustom client-side validation

La convalida lato client personalizzata viene eseguita generando attributi data- HTML che vengono usati con un adapter jQuery Validate personalizzato.Custom client-side validation is done by generating data- HTML attributes that work with a custom jQuery Validate adapter. Il codice dell'adapter di esempio seguente è stato scritto per gli attributi [ClassicMovie] e [ClassicMovieWithClientValidator] presentati precedentemente nell'articolo: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;
});

Per informazioni sulla scrittura degli adapter, vedere la documentazione di jQuery Validate.For information about how to write adapters, see the jQuery Validate documentation.

L'uso di un adapter per un determinato campo viene attivato dagli attributi data-, i quali eseguono le operazioni seguenti:The use of an adapter for a given field is triggered by data- attributes that:

  • Contrassegnano il campo come campo da sottoporre a convalida (data-val="true").Flag the field as being subject to validation (data-val="true").
  • Identificano un nome della regola di convalida e un testo del messaggio di errore, ad esempio data-val-rulename="Error message.".Identify a validation rule name and error message text (for example, data-val-rulename="Error message.").
  • Specificare i parametri aggiuntivi necessari al validator, ad esempio data-val-rulename-param1="value".Provide any additional parameters the validator needs (for example, data-val-rulename-param1="value").

L'esempio seguente contiene gli attributi data- per l'attributo ClassicMovie dell'app di esempio: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="">

Come già accennato in precedenza, gli helper tag e gli helper HTML usano le informazioni degli attributi di convalida per eseguire il rendering degli attributi data-.As noted earlier, Tag Helpers and HTML helpers use information from validation attributes to render data- attributes. Per scrivere il codice che crea attributi HTML data- personalizzati, sono disponibili due opzioni:There are two options for writing code that results in the creation of custom data- HTML attributes:

  • Creare una classe che deriva da AttributeAdapterBase<TAttribute> e una classe che implementa IValidationAttributeAdapterProvider e registrare l'attributo e il relativo adapter nell'inserimento delle dipendenze.Create a class that derives from AttributeAdapterBase<TAttribute> and a class that implements IValidationAttributeAdapterProvider, and register your attribute and its adapter in DI. Questo metodo segue il principio di singola responsabilità in quanto il codice di convalida relativo a server e client si trova in classi separate.This method follows the single responsibility principal in that server-related and client-related validation code is in separate classes. L'adapter offre anche un altro vantaggio. Essendo registrato nell'inserimento delle dipendenze, può usare gli altri servizi disponibili nell'inserimento delle dipendenze se necessario.The adapter also has the advantage that since it is registered in DI, other services in DI are available to it if needed.
  • Implementare IClientModelValidator nella classe ValidationAttribute.Implement IClientModelValidator in your ValidationAttribute class. Questo metodo potrebbe essere appropriato se l'attributo non esegue la convalida lato server e non richiede altri servizi dell'inserimento delle dipendenze.This method might be appropriate if the attribute doesn't do any server-side validation and doesn't need any services from DI.

AttributeAdapter per la convalida lato clientAttributeAdapter for client-side validation

Questo metodo di rendering degli attributi data- in HTML viene usato dall'attributo ClassicMovie nell'app di esempio.This method of rendering data- attributes in HTML is used by the ClassicMovie attribute in the sample app. Per aggiungere la convalida lato client usando questo metodo:To add client validation by using this method:

  1. Creare una classe di adapter dell'attributo per l'attributo di convalida personalizzata.Create an attribute adapter class for the custom validation attribute. Derivare la classe da AttributeAdapterBase<T>.Derive the class from AttributeAdapterBase<T>. Creare un metodo AddValidation che aggiunge gli attributi data- all'output sottoposto a rendering, come illustrato in questo esempio: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. Creare una classe di provider dell'adapter che implementa IValidationAttributeAdapterProvider.Create an adapter provider class that implements IValidationAttributeAdapterProvider. Nel metodo GetAttributeAdapter passare l'attributo personalizzato al costruttore dell'adapter, come illustrato in questo esempio: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. Registrare il provider dell'adapter per l'inserimento delle dipendenze 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 per la convalida lato clientIClientModelValidator for client-side validation

Questo metodo di rendering degli attributi data- in HTML viene usato dall'attributo ClassicMovieWithClientValidator nell'app di esempio.This method of rendering data- attributes in HTML is used by the ClassicMovieWithClientValidator attribute in the sample app. Per aggiungere la convalida lato client usando questo metodo:To add client validation by using this method:

  • Nell'attributo di convalida personalizzato implementare l'interfaccia IClientModelValidator e creare un metodo AddValidation.In the custom validation attribute, implement the IClientModelValidator interface and create an AddValidation method. Nel metodo AddValidation aggiungere gli attributi data- per la convalida, come illustrato nell'esempio seguente: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;
        }
    }
    

Disabilitare la convalida lato clientDisable client-side validation

Il codice seguente disabilita la convalida client in Razor Pages:The following code disables client validation in Razor Pages:

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

Altre opzioni per disabilitare la convalida sul lato client:Other options to disable client-side validation:

  • Impostare come commento il riferimento a _ValidationScriptsPartial in tutti i file con estensione cshtml .Comment out the reference to _ValidationScriptsPartial in all the .cshtml files.
  • Rimuovere il contenuto del file Pages\Shared_ValidationScriptsPartial. cshtml .Remove the contents of the Pages\Shared_ValidationScriptsPartial.cshtml file.

L'approccio precedente non impedisce la convalida lato client di ASP.NET Core libreria di classi Razor Identity.The preceding approach won't prevent client side validation of ASP.NET Core Identity Razor Class Library. Per altre informazioni, vedere Identità di impalcatura nei progetti ASP.NET Core.For more information, see Identità di impalcatura nei progetti ASP.NET Core.

Risorse aggiuntiveAdditional resources

Questo articolo illustra come convalidare l'input utente in un'app ASP.NET Core MVC o Razor Pages.This article explains how to validate user input in an ASP.NET Core MVC or Razor Pages app.

Visualizzare o scaricare il codice di esempio (procedura per il download).View or download sample code (how to download).

Stato del modelloModel state

Lo stato del modello rappresenta gli errori che provengono da due sottosistemi: associazione di modelli e convalida del modello.Model state represents errors that come from two subsystems: model binding and model validation. Gli errori provenienti dall'associazione di modelli sono in genere errori di conversione dei dati, ad esempio l'immissione di una "x" in un campo in cui è previsto un intero.Errors that originate from model binding are generally data conversion errors (for example, an "x" is entered in a field that expects an integer). La convalida del modello è un processo successivo all'associazione di modelli e segnala gli errori in caso di dati non conformi alle regole di business, ad esempio l'immissione del valore 0 in un campo in cui è previsto un valore compreso tra 1 e 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).

Sia l'associazione che la convalida di modelli avviene prima di eseguire un'azione del controller o un metodo gestore di Razor Pages.Both model binding and validation occur before the execution of a controller action or a Razor Pages handler method. Per le app Web, è responsabilità dell'app esaminare ModelState.IsValid e rispondere nel modo appropriato.For web apps, it's the app's responsibility to inspect ModelState.IsValid and react appropriately. Le app Web in genere visualizzare di nuovo la pagina con un messaggio di errore: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");
}

I controller API Web non devono controllare ModelState.IsValid se hanno l'attributo [ApiController].Web API controllers don't have to check ModelState.IsValid if they have the [ApiController] attribute. In tal caso, viene restituita una risposta HTTP 400 automatica contenente i dettagli dell'errore quando lo stato del modello non è valido.In that case, an automatic HTTP 400 response containing error details is returned when model state is invalid. Per altre informazioni, vedere Risposte HTTP 400 automatiche.For more information, see Automatic HTTP 400 responses.

Rieseguire la convalidaRerun validation

La convalida è automatica, ma potrebbe essere necessario ripeterla manualmente.Validation is automatic, but you might want to repeat it manually. Ad esempio, è possibile che si calcoli un valore per una proprietà e che si voglia rieseguire la convalida dopo aver impostato la proprietà sul valore calcolato.For example, you might compute a value for a property and want to rerun validation after setting the property to the computed value. Per rieseguire la convalida, chiamare il metodo TryValidateModel come illustrato di seguito: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);

Attributi di convalidaValidation attributes

Gli attributi di convalida consentono di specificare le regole di convalida per le proprietà del modello.Validation attributes let you specify validation rules for model properties. Nell'esempio seguente dell'app di esempio viene illustrata una classe di modello annotata con attributi di convalida.The following example from the sample app shows a model class that is annotated with validation attributes. [ClassicMovie] è un attributo di convalida personalizzato, mentre gli altri sono attributi predefiniti.The [ClassicMovie] attribute is a custom validation attribute and the others are built-in. Non viene mostrato [ClassicMovie2], che mostra un metodo alternativo per implementare un attributo personalizzato.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; }
}

Attributi predefinitiBuilt-in attributes

Gli attributi di convalida predefiniti includono:Built-in validation attributes include:

  • [CreditCard]: convalida che la proprietà abbia un formato di carta di credito.[CreditCard]: Validates that the property has a credit card format.
  • [Compare]: verifica che due proprietà di un modello corrispondano.[Compare]: Validates that two properties in a model match. Ad esempio, il file Register.cshtml.cs USA [Compare] per convalidare le due password immesse corrispondenti.For example, the Register.cshtml.cs file uses [Compare] to validate the two entered passwords match. Identità del patibolo per visualizzare il codice del registro.Scaffold Identity to see the Register code.
  • [EmailAddress]: convalida che la proprietà abbia un formato di posta elettronica.[EmailAddress]: Validates that the property has an email format.
  • [Phone]: convalida che la proprietà abbia un formato di numero di telefono.[Phone]: Validates that the property has a telephone number format.
  • [Range]: verifica che il valore della proprietà sia compreso in un intervallo specificato.[Range]: Validates that the property value falls within a specified range.
  • [RegularExpression]: verifica che il valore della proprietà corrisponda a un'espressione regolare specificata.[RegularExpression]: Validates that the property value matches a specified regular expression.
  • [Required]: verifica che il campo non sia null.[Required]: Validates that the field is not null. Vedere l'attributo [Required] per informazioni dettagliate sul comportamento di questo attributo.See [Required] attribute for details about this attribute's behavior.
  • [StringLength]: verifica che un valore della proprietà stringa non superi il limite di lunghezza specificato.[StringLength]: Validates that a string property value doesn't exceed a specified length limit.
  • [Url]: convalida che la proprietà abbia un formato URL.[Url]: Validates that the property has a URL format.
  • [Remote]: convalida l'input sul client chiamando un metodo di azione sul server.[Remote]: Validates input on the client by calling an action method on the server. Vedere l'attributo [Remote] per informazioni dettagliate sul comportamento di questo attributo.See [Remote] attribute for details about this attribute's behavior.

Nello spazio dei nomi System.ComponentModel.DataAnnotations è possibile trovare un elenco completo degli attributi di convalida.A complete list of validation attributes can be found in the System.ComponentModel.DataAnnotations namespace.

Messaggi di erroreError messages

Gli attributi di convalida consentono di specificare il messaggio di errore da visualizzare in caso di input non valido.Validation attributes let you specify the error message to be displayed for invalid input. Ad esempio:For example:

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

Internamente gli attributi chiamano String.Format con un segnaposto per il nome campo e talvolta con segnaposto aggiuntivi.Internally, the attributes call String.Format with a placeholder for the field name and sometimes additional placeholders. Ad esempio:For example:

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

Quando applicato a una proprietà Name, il messaggio di errore creato con il codice precedente sarà "La lunghezza del nome utente deve essere compresa tra 6 e 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.".

Per scoprire i parametri passati a String.Format per un messaggio di errore dell'attributo specifico, vedere il codice sorgente DataAnnotations.To find out which parameters are passed to String.Format for a particular attribute's error message, see the DataAnnotations source code.

Attributo [Required][Required] attribute

Per impostazione predefinita, il sistema di convalida considera i parametri non nullable o le proprietà come se avessero un attributo [Required].By default, the validation system treats non-nullable parameters or properties as if they had a [Required] attribute. I tipi di valore decimal e int sono parametri non nullable.Value types such as decimal and int are non-nullable.

Convalida dell'attributo [Required] nel server[Required] validation on the server

Nel server un valore obbligatorio viene considerato mancante se la proprietà è Null.On the server, a required value is considered missing if the property is null. Un campo non nullable è sempre valido e il messaggio di errore dell'attributo [Required] non viene mai visualizzato.A non-nullable field is always valid, and the [Required] attribute's error message is never displayed.

Può però succedere che l'associazione di modelli per una proprietà non nullable abbia esito negativo, generando un messaggio di errore, ad esempio 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. Per specificare un messaggio di errore personalizzato per la convalida lato server di tipi non nullable, sono disponibili le opzioni seguenti:To specify a custom error message for server-side validation of non-nullable types, you have the following options:

  • Il campo deve ammettere i valori Null, ad esempio decimal? anziché decimal.Make the field nullable (for example, decimal? instead of decimal). I tipi di valore Nullable<T> vengono considerati tipi nullable standard.Nullable<T> value types are treated like standard nullable types.

  • Specificare il messaggio di errore predefinito che l'associazione di modelli deve usare, come illustrato nell'esempio seguente: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>();
    

    Per altre informazioni sugli errori dell'associazione di modelli che possono essere impostati come messaggi predefiniti, vedere DefaultModelBindingMessageProvider.For more information about model binding errors that you can set default messages for, see DefaultModelBindingMessageProvider.

Convalida dell'attributo [Required] nel client[Required] validation on the client

Le stringhe e i tipi non nullable sono gestiti in modo diverso nel client rispetto a come vengono gestiti nel server.Non-nullable types and strings are handled differently on the client compared to the server. Nel client:On the client:

  • Un valore viene considerato presente solo viene immesso un input per tale valore.A value is considered present only if input is entered for it. La convalida lato client gestisce quindi i tipi non nullable come i tipi nullable.Therefore, client-side validation handles non-nullable types the same as nullable types.
  • Lo spazio vuoto in un campo stringa viene considerato un input valido per il metodo required della convalida di jQuery.Whitespace in a string field is considered valid input by the jQuery Validation required method. La convalida lato server considera un campo stringa obbligatorio non valido solo se viene immesso uno spazio vuoto.Server-side validation considers a required string field invalid if only whitespace is entered.

Come indicato in precedenza, i tipi non nullable vengono trattati come se avessero un attributo [Required].As noted earlier, non-nullable types are treated as though they had a [Required] attribute. Quindi viene eseguita la convalida lato client anche se non si applica l'attributo [Required].That means you get client-side validation even if you don't apply the [Required] attribute. Se invece non si usa l'attributo, viene visualizzato un messaggio di errore predefinito.But if you don't use the attribute, you get a default error message. Per specificare un messaggio di errore personalizzato, usare l'attributo.To specify a custom error message, use the attribute.

Attributo [Remote][Remote] attribute

L'attributo [Remote] implementa la convalida lato client che richiede la chiamata a un metodo nel server per determinare se l'input del campo è valido.The [Remote] attribute implements client-side validation that requires calling a method on the server to determine whether field input is valid. Ad esempio, l'app potrebbe dover verificare se un nome utente è già in uso.For example, the app may need to verify whether a user name is already in use.

Per implementare la convalida remota:To implement remote validation:

  1. Creare un metodo di azione per JavaScript da chiamare.Create an action method for JavaScript to call. Il metodo remote jQuery Validate prevede una risposta JSON:The jQuery Validate remote method expects a JSON response:

    • "true" indica che i dati di input sono validi."true" means the input data is valid.
    • "false", undefined o null indica che l'input non è valido."false", undefined, or null means the input is invalid. Visualizzare il messaggio di errore predefinito.Display the default error message.
    • Qualsiasi altra stringa indica che l'input non è valido.Any other string means the input is invalid. Visualizzare la stringa come messaggio di errore personalizzato.Display the string as a custom error message.

    Di seguito è riportato un esempio di un metodo di azione che restituisce un messaggio di errore personalizzato: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. Nella classe del modello annotare la proprietà con un attributo [Remote] che punta al metodo di azione di convalida, come illustrato nell'esempio seguente: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; }
    

    L'attributo [Remote] si trova nello spazio dei nomi Microsoft.AspNetCore.Mvc.The [Remote] attribute is in the Microsoft.AspNetCore.Mvc namespace. Installare il pacchetto NuGet Microsoft.AspNetCore.Mvc.ViewFeatures se non si usa il metapacchetto Microsoft.AspNetCore.App o Microsoft.AspNetCore.All.Install the Microsoft.AspNetCore.Mvc.ViewFeatures NuGet package if you're not using the Microsoft.AspNetCore.App or Microsoft.AspNetCore.All metapackage.

Campi aggiuntiviAdditional fields

La proprietà AdditionalFields dell'attributo [Remote] consente di convalidare combinazioni di campi rispetto ai dati nel server.The AdditionalFields property of the [Remote] attribute lets you validate combinations of fields against data on the server. Ad esempio, se il modello User avesse le proprietà FirstName e LastName, potrebbe essere necessario controllare che non siano già esistenti utenti con la stessa coppia di nomi.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. Nell'esempio riportato di seguito viene illustrato come usare 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; }

È stato possibile impostare in modo esplicito AdditionalFields sulle stringhe "FirstName" e "LastName", ma usando l'operatore nameof il successivo refactoring risulta semplificato.AdditionalFields could be set explicitly to the strings "FirstName" and "LastName", but using the nameof operator simplifies later refactoring. Il metodo di azione per la convalida deve accettare gli argomenti sia per il nome e sia per il cognome: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);
}

Quando si immette un nome o un cognome, JavaScript esegue una chiamata remota per verificare se tale coppia di nomi è in uso.When the user enters a first or last name, JavaScript makes a remote call to see if that pair of names has been taken.

Per convalidare due o più campi aggiuntivi, specificarli sotto forma di elenco delimitato da virgole.To validate two or more additional fields, provide them as a comma-delimited list. Ad esempio, per aggiungere una proprietà MiddleName al modello, impostare l'attributo [Remote] come illustrato nell'esempio seguente: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, come tutti gli argomenti dell'attributo, deve essere un'espressione costante.AdditionalFields, like all attribute arguments, must be a constant expression. Non usare quindi una stringa interpolata oppure chiamare Join per inizializzare AdditionalFields.Therefore, don't use an interpolated string or call Join to initialize AdditionalFields.

Alternative agli attributi predefinitiAlternatives to built-in attributes

Se si vuole usare un tipo di convalida non definita da attributi predefiniti, è possibile eseguire le operazioni seguenti:If you need validation not provided by built-in attributes, you can:

Attributi personalizzatiCustom attributes

Per gli scenari non gestiti dagli attributi di convalida predefiniti, è possibile creare attributi di convalida personalizzati.For scenarios that the built-in validation attributes don't handle, you can create custom validation attributes. Creare una classe che eredita da ValidationAttribute ed eseguire l'override del metodo IsValid.Create a class that inherits from ValidationAttribute, and override the IsValid method.

Il metodo IsValid accetta un oggetto denominato value, ovvero l'input da convalidare.The IsValid method accepts an object named value, which is the input to be validated. Un overload accetta anche un oggetto ValidationContext, che contiene informazioni aggiuntive, ad esempio l'istanza del modello creato dall'associazione di modelli.An overload also accepts a ValidationContext object, which provides additional information, such as the model instance created by model binding.

Nell'esempio seguente si convalida che la data di uscita di un film di genere Classic non sia successiva a un anno specifico.The following example validates that the release date for a movie in the Classic genre isn't later than a specified year. L'attributo [ClassicMovie2] prima controlla il genere, poi prosegue solo se il genere è Classic.The [ClassicMovie2] attribute checks the genre first and continues only if it's Classic. Per i film identificati come classici, controlla la data di uscita per verificare che non sia successiva al limite passato al costruttore dell'attributo.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}.";
    }
}

La variabile movie nell'esempio precedente rappresenta un oggetto Movie contenente i dati dell'invio del modulo.The movie variable in the preceding example represents a Movie object that contains the data from the form submission. Il metodo IsValid controlla la data e il genere.The IsValid method checks the date and genre. Se la convalida ha esito positivo, IsValid restituisce un codice ValidationResult.Success.Upon successful validation, IsValid returns a ValidationResult.Success code. Se la convalida ha esito negativo, viene restituito un codice ValidationResult con un messaggio di errore.When validation fails, a ValidationResult with an error message is returned.

IValidatableObjectIValidatableObject

L'esempio precedente usa solo tipi Movie.The preceding example works only with Movie types. Un'altra opzione per la convalida a livello di classe consiste nell'implementare IValidatableObject nella classe del modello, come illustrato nell'esempio seguente: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" });
        }
    }
}

Convalida del nodo di primo livelloTop-level node validation

I nodi di primo livello includono:Top-level nodes include:

  • Parametri di azioneAction parameters
  • Proprietà del controllerController properties
  • Parametri del gestore di paginaPage handler parameters
  • Proprietà del modello di paginaPage model properties

Vengono convalidati i nodi di primo livello associati al modello, oltre a convalidare le proprietà del modello.Model-bound top-level nodes are validated in addition to validating model properties. Nell'esempio seguente dell'app di esempio il metodo VerifyPhone usa RegularExpressionAttribute per convalidare il parametro di azione phone: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);
}

I nodi di primo livello possono usare BindRequiredAttribute con gli attributi di convalida.Top-level nodes can use BindRequiredAttribute with validation attributes. Nell'esempio seguente dall'app di esempio, il metodo CheckAge specifica che il parametro age deve essere associato dalla stringa di query quando viene inviato il modulo: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)
{

La pagina Check Age (CheckAge.cshtml), include due moduli.In the Check Age page (CheckAge.cshtml), there are two forms. Il primo modulo invia un valore Age 99 come stringa di query: 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.

Quando viene inviato un parametro correttamente formattato age dalla stringa di query, il modulo viene convalidato.When a properly formatted age parameter from the query string is submitted, the form validates.

Il secondo modulo nella pagina Check Age invia il valore Age nel corpo della richiesta e la convalida ha esito negativo.The second form on the Check Age page submits the Age value in the body of the request, and validation fails. L'associazione non riesce perché il parametro age deve provenire da una stringa di query.Binding fails because the age parameter must come from a query string.

Quando viene eseguita con CompatibilityVersion.Version_2_1 o versione successiva, la convalida del nodo di primo livello è abilitata per impostazione predefinita.When running with CompatibilityVersion.Version_2_1 or later, top-level node validation is enabled by default. In caso contrario, la convalida del nodo di primo livello è disabilitata.Otherwise, top-level node validation is disabled. L'opzione predefinita può essere sovrascritta impostando la proprietà AllowValidatingTopLevelNodes in (Startup.ConfigureServices), come illustrato di seguito: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);

Numero massimo di erroriMaximum errors

La convalida si interrompe quando viene raggiunto il numero di errori (200 per impostazione predefinita).Validation stops when the maximum number of errors is reached (200 by default). È possibile configurare questo numero con il codice seguente in 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>();

Numero massimo di ricorsioniMaximum recursion

ValidationVisitor attraversare l'oggetto grafico del modello che deve essere convalidato.ValidationVisitor traverses the object graph of the model being validated. Per i modelli molti profondi o ricorsivi all'infinito, la convalida può generare un overflow dello stack.For models that are very deep or are infinitely recursive, validation may result in stack overflow. MvcOptions.MaxValidationDepth consente di arrestare tempestivamente la convalida se la ricorsione del visitatore supera la profondità configurata.MvcOptions.MaxValidationDepth provides a way to stop validation early if the visitor recursion exceeds a configured depth. Il valore predefinito di MvcOptions.MaxValidationDepth è 32 quando viene eseguito con CompatibilityVersion.Version_2_2 o versione successiva.The default value of MvcOptions.MaxValidationDepth is 32 when running with CompatibilityVersion.Version_2_2 or later. Per le versioni precedenti, il valore è Null, vale a dire che non esistono limiti di profondità.For earlier versions, the value is null, which means no depth constraint.

Corto circuito automaticoAutomatic short-circuit

La convalida viene ignorata automaticamente (corto circuito) se l'oggetto grafico non richiede la convalida.Validation is automatically short-circuited (skipped) if the model graph doesn't require validation. Gli oggetti per cui viene ignorata la convalida sono le raccolte di primitive (ad esempio byte[], string[], Dictionary<string, string>) e gli oggetti grafici complessi che non hanno validator.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.

Disabilitare la convalidaDisable validation

Per disabilitare la convalida:To disable validation:

  1. Creare un'implementazione di IObjectModelValidator che non contrassegna i campi come non validi.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. Aggiungere il codice seguente a Startup.ConfigureServices per sostituire l'impostazione IObjectModelValidator predefinita nel contenitore di inserimento delle dipendenze.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());
    

Potrebbero essere visualizzati errori di stato del modello generati dall'associazione di modelli.You might still see model state errors that originate from model binding.

Convalida lato clientClient-side validation

La convalida lato client non consente l'invio del modulo finché non è ritenuto valido.Client-side validation prevents submission until the form is valid. Tramite il pulsante Invia viene eseguito JavaScript, che invia il modulo oppure visualizza i messaggi di errore.The Submit button runs JavaScript that either submits the form or displays error messages.

La convalida lato client evitare un inutile round trip al server in caso di errori di input in un modulo.Client-side validation avoids an unnecessary round trip to the server when there are input errors on a form. I riferimenti dello script seguenti in _Layout.cshtml e _ValidationScriptsPartial.cshtml supportano la convalida lato client: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>

Lo script jQuery Unobtrusive Validation è una libreria front-end Microsoft personalizzata che si basa sul noto plug-in jQuery Validate.The jQuery Unobtrusive Validation script is a custom Microsoft front-end library that builds on the popular jQuery Validate plugin. Senza Query Unobtrusive Validation, sarebbe necessario scrivere il codice della stessa logica di convalida in due posizioni, vale a dire negli attributi di convalida lato server nelle proprietà del modello e nuovamente negli script lato client.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. Invece, gli helper tage agli helper HTML usano gli attributi di convalida e i metadati di tipo delle proprietà del modello per eseguire il rendering degli attributi data- HTML 5 negli elementi del modulo che devono essere convalidati.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. jQuery Unobtrusive Validation analizza gli attributi data- e passa la logica a jQuery Validate, "copiando" in modo efficace la logica di convalida lato server nel client.jQuery Unobtrusive Validation parses the data- attributes and passes the logic to jQuery Validate, effectively "copying" the server-side validation logic to the client. È possibile visualizzare gli errori di convalida nel client tramite gli helper tag, come illustrato di seguito: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>

Gli helper tag precedenti eseguono il rendering del codice HTML seguente.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>

Si noti che gli attributi data- nell'output HTML corrispondono agli attributi di convalida per la proprietà ReleaseDate.Notice that the data- attributes in the HTML output correspond to the validation attributes for the ReleaseDate property. L'attributo data-val-required contiene un messaggio di errore che viene visualizzato se l'utente non compila il campo relativo alla data di uscita.The data-val-required attribute contains an error message to display if the user doesn't fill in the release date field. Lo script jQuery Unobtrusive Validation passa questo valore al metodo required() jQuery Validate, che visualizza il messaggio nell'elemento <span> di accompagnamento.jQuery Unobtrusive Validation passes this value to the jQuery Validate required() method, which then displays that message in the accompanying <span> element.

La convalida del tipo di dati si basa sul tipo .NET di una proprietà, a meno che sia sostituito dall'attributo [DataType].Data type validation is based on the .NET type of a property, unless that is overridden by a [DataType] attribute. I browser generano messaggi di errore predefiniti propri che il pacchetto jQuery Validation Unobtrusive Validation può comunque sostituire.Browsers have their own default error messages, but the jQuery Validation Unobtrusive Validation package can override those messages. Gli attributi [DataType] e le sottoclassi, ad esempio [EmailAddress], consentono di specificare il messaggio di errore.[DataType] attributes and subclasses such as [EmailAddress] let you specify the error message.

Aggiungere la convalida a moduli dinamiciAdd Validation to Dynamic Forms

Quando la pagina viene caricata, jQuery Unobtrusive Validation passa la logica e i parametri di convalida a jQuery Validate.jQuery Unobtrusive Validation passes validation logic and parameters to jQuery Validate when the page first loads. La convalida non viene quindi eseguita automaticamente nei moduli generati in modo dinamico.Therefore, validation doesn't work automatically on dynamically generated forms. Per abilitare la convalida, chiedere a jQuery Unobtrusive Validation di analizzare il modulo dinamico immediatamente dopo essere stato creato.To enable validation, tell jQuery Unobtrusive Validation to parse the dynamic form immediately after you create it. Il codice riportato di seguito configura ad esempio la convalida lato client in un modulo che è stato aggiunto tramite 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);
    }
})

Il metodo $.validator.unobtrusive.parse() accetta un selettore jQuery per ogni argomento.The $.validator.unobtrusive.parse() method accepts a jQuery selector for its one argument. Questo metodo indica a jQuery Unobtrusive Validation di analizzare gli attributi data- dei moduli all'interno di tale tipo di selettore.This method tells jQuery Unobtrusive Validation to parse the data- attributes of forms within that selector. I valori di tali attributi vengono quindi passati al plug-in jQuery Validate.The values of those attributes are then passed to the jQuery Validate plugin.

Aggiungere la convalida a controlli dinamiciAdd Validation to Dynamic Controls

Il metodo $.validator.unobtrusive.parse() funziona su un intero modulo e non sui singoli controlli generati dinamicamente, ad esempio <input> e <select/>.The $.validator.unobtrusive.parse() method works on an entire form, not on individual dynamically generated controls, such as <input> and <select/>. Per eseguire il reparse del modulo, rimuovere i dati di convalida aggiunti quando il modulo è stato precedentemente analizzato, come illustrato nell'esempio seguente: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);
    }
})

Convalida lato client personalizzataCustom client-side validation

La convalida lato client personalizzata viene eseguita generando attributi data- HTML che vengono usati con un adapter jQuery Validate personalizzato.Custom client-side validation is done by generating data- HTML attributes that work with a custom jQuery Validate adapter. Il codice dell'adapter di esempio seguente è stato scritto per gli attributi ClassicMovie e ClassicMovie2 presentati precedentemente nell'articolo: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;
    });

Per informazioni sulla scrittura degli adapter, vedere la documentazione di jQuery Validate.For information about how to write adapters, see the jQuery Validate documentation.

L'uso di un adapter per un determinato campo viene attivato dagli attributi data-, i quali eseguono le operazioni seguenti:The use of an adapter for a given field is triggered by data- attributes that:

  • Contrassegnano il campo come campo da sottoporre a convalida (data-val="true").Flag the field as being subject to validation (data-val="true").
  • Identificano un nome della regola di convalida e un testo del messaggio di errore, ad esempio data-val-rulename="Error message.".Identify a validation rule name and error message text (for example, data-val-rulename="Error message.").
  • Specificare i parametri aggiuntivi necessari al validator, ad esempio data-val-rulename-parm1="value".Provide any additional parameters the validator needs (for example, data-val-rulename-parm1="value").

L'esempio seguente contiene gli attributi data- per l'attributo ClassicMovie dell'app di esempio: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="">

Come già accennato in precedenza, gli helper tag e gli helper HTML usano le informazioni degli attributi di convalida per eseguire il rendering degli attributi data-.As noted earlier, Tag Helpers and HTML helpers use information from validation attributes to render data- attributes. Per scrivere il codice che crea attributi HTML data- personalizzati, sono disponibili due opzioni:There are two options for writing code that results in the creation of custom data- HTML attributes:

  • Creare una classe che deriva da AttributeAdapterBase<TAttribute> e una classe che implementa IValidationAttributeAdapterProvider e registrare l'attributo e il relativo adapter nell'inserimento delle dipendenze.Create a class that derives from AttributeAdapterBase<TAttribute> and a class that implements IValidationAttributeAdapterProvider, and register your attribute and its adapter in DI. Questo metodo segue il principio di singola responsabilità in quanto il codice di convalida relativo a server e client si trova in classi separate.This method follows the single responsibility principal in that server-related and client-related validation code is in separate classes. L'adapter offre anche un altro vantaggio. Essendo registrato nell'inserimento delle dipendenze, può usare gli altri servizi disponibili nell'inserimento delle dipendenze se necessario.The adapter also has the advantage that since it is registered in DI, other services in DI are available to it if needed.
  • Implementare IClientModelValidator nella classe ValidationAttribute.Implement IClientModelValidator in your ValidationAttribute class. Questo metodo potrebbe essere appropriato se l'attributo non esegue la convalida lato server e non richiede altri servizi dell'inserimento delle dipendenze.This method might be appropriate if the attribute doesn't do any server-side validation and doesn't need any services from DI.

AttributeAdapter per la convalida lato clientAttributeAdapter for client-side validation

Questo metodo di rendering degli attributi data- in HTML viene usato dall'attributo ClassicMovie nell'app di esempio.This method of rendering data- attributes in HTML is used by the ClassicMovie attribute in the sample app. Per aggiungere la convalida lato client usando questo metodo:To add client validation by using this method:

  1. Creare una classe di adapter dell'attributo per l'attributo di convalida personalizzata.Create an attribute adapter class for the custom validation attribute. Derivare la classe da AttributeAdapterBase<T>.Derive the class from AttributeAdapterBase<T>. Creare un metodo AddValidation che aggiunge gli attributi data- all'output sottoposto a rendering, come illustrato in questo esempio: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. Creare una classe di provider dell'adapter che implementa IValidationAttributeAdapterProvider.Create an adapter provider class that implements IValidationAttributeAdapterProvider. Nel metodo GetAttributeAdapter passare l'attributo personalizzato al costruttore dell'adapter, come illustrato in questo esempio: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. Registrare il provider dell'adapter per l'inserimento delle dipendenze 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 per la convalida lato clientIClientModelValidator for client-side validation

Questo metodo di rendering degli attributi data- in HTML viene usato dall'attributo ClassicMovie2 nell'app di esempio.This method of rendering data- attributes in HTML is used by the ClassicMovie2 attribute in the sample app. Per aggiungere la convalida lato client usando questo metodo:To add client validation by using this method:

  • Nell'attributo di convalida personalizzato implementare l'interfaccia IClientModelValidator e creare un metodo AddValidation.In the custom validation attribute, implement the IClientModelValidator interface and create an AddValidation method. Nel metodo AddValidation aggiungere gli attributi data- per la convalida, come illustrato nell'esempio seguente: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].";
        }
    }
    

Disabilitare la convalida lato clientDisable client-side validation

Il codice seguente disabilita la convalida lato client nelle visualizzazioni MVC:The following code disables client validation in MVC views:

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

E in Razor Pages:And in Razor Pages:

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

Un'altra opzione per disabilitare la convalida lato client consiste nell'impostare come commento il riferimento a _ValidationScriptsPartial nel file .cshtml.Another option for disabling client validation is to comment out the reference to _ValidationScriptsPartial in your .cshtml file.

Risorse aggiuntiveAdditional resources