Convalida dell'input utente nei siti Pagine Web ASP.NET (Razor)

di Tom FitzMacken

Questo articolo illustra come convalidare le informazioni ottenute dagli utenti, ovvero per assicurarsi che gli utenti immettono informazioni valide nei moduli HTML in un sito Pagine Web ASP.NET (Razor).

Contenuto dell'esercitazione:

  • Come verificare che l'input di un utente corrisponda ai criteri di convalida definiti.
  • Come determinare se tutti i test di convalida sono passati.
  • Come visualizzare gli errori di convalida (e come formattarli).
  • Come convalidare i dati che non provengono direttamente dagli utenti.

Questi sono i concetti di programmazione ASP.NET introdotti nell'articolo:

  • Helper Validation .
  • Metodi Html.ValidationSummary e Html.ValidationMessage.

Versioni software usate nell'esercitazione

  • Pagine Web ASP.NET (Razor) 3

Questa esercitazione funziona anche con Pagine Web ASP.NET 2.

In questo articolo sono contenute le sezioni seguenti:

Panoramica della convalida dell'input utente

Se si chiede agli utenti di immettere informazioni in una pagina, ad esempio in un modulo, è importante assicurarsi che i valori immessi siano validi. Ad esempio, non si vuole elaborare un modulo che manca di informazioni critiche.

Quando gli utenti immettono valori in un modulo HTML, i valori immessi sono stringhe. In molti casi, i valori necessari sono alcuni altri tipi di dati, ad esempio numeri interi o date. È quindi necessario assicurarsi che i valori immessi dagli utenti possano essere convertiti correttamente nei tipi di dati appropriati.

È anche possibile che siano presenti determinate restrizioni sui valori. Anche se gli utenti immettono correttamente un intero, ad esempio, potrebbe essere necessario assicurarsi che il valore rientra all'interno di un determinato intervallo.

Screenshot che mostra gli errori di convalida che usano classi di stile CSS.

Nota

Importante La convalida dell'input utente è importante anche per la sicurezza. Quando si limitano i valori che gli utenti possono immettere nei moduli, è possibile ridurre la possibilità che un utente possa immettere un valore che possa compromettere la sicurezza del sito.

Convalida dell'input utente

In Pagine Web ASP.NET 2 è possibile usare l'helper per testare l'input Validator dell'utente. L'approccio di base consiste nell'eseguire le operazioni seguenti:

  1. Determinare gli elementi di input (campi) da convalidare.

    I valori vengono in genere convalidati in <input> elementi in un modulo. Tuttavia, è consigliabile convalidare tutti gli input, anche l'input proveniente da un elemento vincolato come un <select> elenco. Ciò consente di assicurarsi che gli utenti non ignorano i controlli in una pagina e inviino un modulo.

  2. Nel codice della pagina aggiungere singoli controlli di convalida per ogni elemento di input usando metodi dell'helper Validation .

    Per verificare la presenza di campi obbligatori, usare Validation.RequireField(field, [error message]) (per un singolo campo) o Validation.RequireFields(field1, field2, ...)) (per un elenco di campi). Per altri tipi di convalida, usare Validation.Add(field, ValidationType). Per ValidationType, è possibile usare queste opzioni:

    Validator.DateTime ([error message])
    Validator.Decimal([error message])
    Validator.EqualsTo(otherField [, error message])
    Validator.Float([error message])
    Validator.Integer([error message])
    Validator.Range(min, max [, error message])
    Validator.RegEx(pattern [, error message])
    Validator.Required([error message])
    Validator.StringLength(length)
    Validator.Url([error message])

  3. Quando la pagina viene inviata, verificare se la convalida è passata controllando Validation.IsValid:

    if(IsPost && Validation.IsValid()){
        // Process form submit
    }
    

    Se si verificano errori di convalida, ignorare la normale elaborazione di pagine. Ad esempio, se lo scopo della pagina è aggiornare un database, non si esegue questa operazione finché non sono stati risolti tutti gli errori di convalida.

  4. Se si verificano errori di convalida, visualizzare i messaggi di errore nel markup della pagina usando Html.ValidationSummary o Html.ValidationMessageo entrambi.

Nell'esempio seguente viene illustrata una pagina che illustra questi passaggi.

@{
    var message="";
    // Specify validation requirements for different fields.
    Validation.RequireField("coursename", "Class name is required");
    Validation.RequireField("credits", "Credits is required");
    Validation.Add("coursename", Validator.StringLength(5));
    Validation.Add("credits", Validator.Integer("Credits must be an integer"));
    Validation.Add("credits", Validator.Range(1, 5, "Credits must be between 1 and 5"));
    Validation.Add("startDate", Validator.DateTime("Start date must be a date"));

    if (IsPost)  {
        // Before processing anything, make sure that all user input is valid.
        if (Validation.IsValid()) {
            var coursename = Request["coursename"];
            var credits = Request["credits"].AsInt();
            var startDate = Request["startDate"].AsDateTime();
            message += @"For Class, you entered " + coursename;
            message += @"<br/>For Credits, you entered " + credits.ToString();
            message += @"<br/>For Start Date, you entered " + startDate.ToString("dd-MMM-yyyy");

            // Further processing here
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Validation Example</title>
  <style>
      body {margin: 1in; font-family: 'Segoe UI'; font-size: 11pt; }
   </style>
</head>
<body>
  <h1>Validation Example</h1>
  <p>This example page asks the user to enter information about some classes at school.</p>
  <form method="post">
    @Html.ValidationSummary()
    <div>
      <label for="coursename">Course name: </label>
      <input type="text"
         name="coursename"
         value="@Request["coursename"]"
      />
      @Html.ValidationMessage("coursename")
    </div>

    <div>
      <label for="credits">Credits: </label>
      <input type="text"
         name="credits"
         value="@Request["credits"]"
      />
      @Html.ValidationMessage("credits")
    </div>

    <div>
      <label for="startDate">Start date: </label>
      <input type="text"
         name="startDate"
         value="@Request["startDate"]"
      />
      @Html.ValidationMessage("startDate")
    </div>

   <div>
      <input type="submit" value="Submit" class="submit" />
    </div>

    <div>
      @if(IsPost){
        <p>@Html.Raw(message)</p>
      }
    </div>
  </form>
</body>
</html>

Per vedere il funzionamento della convalida, eseguire questa pagina e fare intenzionalmente errori. Ad esempio, ecco l'aspetto della pagina se si dimentica di immettere un nome del corso, se si immette un oggetto e se si immette una data non valida:

Errori di convalida nella pagina di cui è stato eseguito il rendering

Aggiunta della convalida lato client

Per impostazione predefinita, l'input utente viene convalidato dopo che gli utenti inviano la pagina, ovvero la convalida viene eseguita nel codice del server. Uno svantaggio di questo approccio è che gli utenti non sanno che hanno fatto un errore fino a quando non inviano la pagina. Se un modulo è lungo o complesso, segnalare errori solo dopo l'invio della pagina può essere scomodo per l'utente.

È possibile aggiungere il supporto per eseguire la convalida nello script client. In tal caso, la convalida viene eseguita come utenti funzionano nel browser. Si supponga, ad esempio, di specificare che un valore deve essere un intero. Se un utente immette un valore non intero, l'errore viene segnalato non appena l'utente lascia il campo di immissione. Gli utenti ottengono un feedback immediato, che è pratico per loro. La convalida basata su client può anche ridurre il numero di volte in cui l'utente deve inviare il modulo per correggere più errori.

Nota

Anche se si usa la convalida lato client, la convalida viene sempre eseguita nel codice del server. L'esecuzione della convalida nel codice del server è una misura di sicurezza, nel caso in cui gli utenti ignorano la convalida basata su client.

  1. Registrare le librerie JavaScript seguenti nella pagina:

    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js">
    </script>
    <script
    src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.js">
    </script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js">
    </script>
    

    Due delle librerie sono caricabili da una rete di distribuzione del contenuto (CDN), quindi non è necessariamente necessario usarli nel computer o nel server. Tuttavia, è necessario disporre di una copia locale di jquery.validate.unobtrusive.js. Se non si lavora già con un modello WebMatrix (ad esempio Il sito iniziale) che include la libreria, creare un sito Pagine Web basato sul sito iniziale. Copiare quindi il file .js nel sito corrente.

  2. Nel markup, per ogni elemento che si sta convalidando, aggiungere una chiamata a Validation.For(field). Questo metodo genera attributi usati dalla convalida lato client. Anziché emettere codice JavaScript effettivo, il metodo genera attributi come data-val-.... Questi attributi supportano la convalida client non intrusiva che usa jQuery per eseguire il lavoro.

Nella pagina seguente viene illustrato come aggiungere funzionalità di convalida client all'esempio illustrato in precedenza.

@{
    // Note that client validation as implemented here will work only with
    // ASP.NET Web Pages 2.

    var message="";
    // Specify validation requirements for different fields.
    Validation.RequireField("coursename", "Class name is required");
    Validation.RequireField("credits", "Credits is required");
    Validation.Add("coursename", Validator.StringLength(5));
    Validation.Add("credits", Validator.Integer("Credits must be an integer"));
    Validation.Add("credits", Validator.Range(1, 5, "Credits must be between 1 and 5"));
    Validation.Add("startDate", Validator.DateTime("Start date must be a date"));

    if (IsPost)  {
        // Before processing anything, make sure that all user input is valid.
        if (Validation.IsValid()) {
            var coursename = Request["coursename"];
            var credits = Request["credits"].AsInt();
            var startDate = Request["startDate"].AsDateTime();
            message += @"For Class, you entered " + coursename;
            message += @"<br/>For Credits, you entered " + credits.ToString();
            message += @"<br/>For Start Date, you entered " + startDate.ToString("dd-MMM-yyyy");

            // Further processing here
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Validation Example with Client Validation</title>
  <style>
      body {margin: 1in; font-family: 'Segoe UI'; font-size: 11pt; }
   </style>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js"></script>
    <script
        src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.js">
    </script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
  <h1>Validation Example with Client Validation</h1>
  <p>This example page asks the user to enter information about some classes at school.</p>
  <form method="post">
    @Html.ValidationSummary()
    <div>
      <label for="coursename">Course name: </label>
      <input type="text"
         name="coursename"
         value="@Request["coursename"]"
         @Validation.For("coursename")
      />
      @Html.ValidationMessage("coursename")
    </div>

    <div>
      <label for="credits">Credits: </label>
      <input type="text"
         name="credits"
         value="@Request["credits"]"
         @Validation.For("credits")
      />
      @Html.ValidationMessage("credits")
    </div>

    <div>
      <label for="startDate">Start date: </label>
      <input type="text"
         name="startDate"
         value="@Request["startDate"]"
         @Validation.For("startDate")
      />
      @Html.ValidationMessage("startDate")
    </div>

   <div>
      <input type="submit" value="Submit" class="submit" />
    </div>

    <div>
      @if(IsPost){
        <p>@Html.Raw(message)</p>
      }
    </div>
  </form>
</body>
</html>

Non tutti i controlli di convalida vengono eseguiti nel client. In particolare, la convalida dei tipi di dati (integer, data e così via) non viene eseguita nel client. I controlli seguenti funzionano sia sul client che sul server:

  • Required
  • Range(minValue, maxValue)
  • StringLength(maxLength[, minLength])
  • Regex(pattern)
  • EqualsTo(otherField)

In questo esempio il test per una data valida non funzionerà nel codice client. Tuttavia, il test verrà eseguito nel codice del server.

Formattazione degli errori di convalida

È possibile controllare la modalità di visualizzazione degli errori di convalida definendo classi CSS con i nomi riservati seguenti:

  • field-validation-error. Definisce l'output Html.ValidationMessage del metodo quando viene visualizzato un errore.
  • field-validation-valid. Definisce l'output Html.ValidationMessage del metodo quando non è presente alcun errore.
  • input-validation-error. Definisce la modalità <input> di rendering degli elementi quando si verifica un errore. Ad esempio, è possibile usare questa classe per impostare il colore di sfondo di un <elemento di input> su un colore diverso se il valore non è valido. Questa classe CSS viene usata solo durante la convalida client (in Pagine Web ASP.NET 2).
  • input-validation-valid. Definisce l'aspetto degli <input> elementi quando non è presente alcun errore.
  • validation-summary-errors. Definisce l'output del Html.ValidationSummary metodo che visualizza un elenco di errori.
  • validation-summary-valid. Definisce l'output Html.ValidationSummary del metodo quando non è presente alcun errore.

Il blocco seguente <style> mostra le regole per le condizioni di errore.

<style>
.validation-summary-errors {
  border:2px solid red;
  color:red;
  font-weight:bold;
  margin:6px;
  width:30%;
}

.field-validation-error{
  color:red;
   font-weight:bold;
   background-color:yellow;
}

.input-validation-error{
  color:red;
  font-weight:bold;
  background-color:pink;
}
</style>

Se si include questo blocco di stile nelle pagine di esempio precedenti nell'articolo, la visualizzazione degli errori sarà simile alla figura seguente:

Errori di convalida che usano classi di stile CSS

Nota

Se non si usa la convalida client in Pagine Web ASP.NET 2, le classi CSS per gli <input> elementi (input-validation-error e input-validation-valid non hanno alcun effetto.

Visualizzazione degli errori statici e dinamici

Le regole CSS sono disponibili in coppie, ad esempio validation-summary-errors e validation-summary-valid. Queste coppie consentono di definire regole per entrambe le condizioni: una condizione di errore e una condizione "normale" (non errore). È importante comprendere che il markup per la visualizzazione degli errori viene sempre eseguito il rendering, anche se non sono presenti errori. Ad esempio, se una pagina ha un Html.ValidationSummary metodo nel markup, l'origine della pagina conterrà il markup seguente anche quando la pagina viene richiesta per la prima volta:

<div class="validation-summary-valid" data-valmsg-summary="true"><ul></ul></div>

In altre parole, il metodo esegue sempre il Html.ValidationSummary rendering di un <div> elemento e di un elenco, anche se l'elenco degli errori è vuoto. Analogamente, il metodo esegue sempre il Html.ValidationMessage rendering di un <span> elemento come segnaposto per un singolo errore di campo, anche se non è presente alcun errore.

In alcune situazioni, la visualizzazione di un messaggio di errore può causare il reflow della pagina e può causare lo spostamento degli elementi nella pagina. Le regole CSS che terminano -valid consentono di definire un layout che consente di evitare questo problema. Ad esempio, è possibile definire field-validation-error e field-validation-valid avere entrambe le stesse dimensioni fisse. In questo modo, l'area di visualizzazione per il campo è statica e non modifica il flusso della pagina se viene visualizzato un messaggio di errore.

Convalida dei dati che non provengono direttamente dagli utenti

A volte è necessario convalidare le informazioni che non provengono direttamente da un modulo HTML. Un esempio tipico è una pagina in cui un valore viene passato in una stringa di query, come nell'esempio seguente:

http://server/myapp/EditClassInformation?classid=1022

In questo caso, si vuole assicurarsi che il valore passato alla pagina (qui, 1022 per il valore di classid) sia valido. Non è possibile usare direttamente l'helper Validation per eseguire questa convalida. È tuttavia possibile usare altre funzionalità del sistema di convalida, ad esempio la possibilità di visualizzare i messaggi di errore di convalida.

Nota

Importante Convalidare sempre i valori che si ottengono da qualsiasi origine, inclusi i valori del campo modulo, i valori della stringa di query e i valori dei cookie. È facile per gli utenti modificare questi valori (ad esempio per scopi dannosi). È quindi necessario controllare questi valori per proteggere l'applicazione.

Nell'esempio seguente viene illustrato come convalidare un valore passato in una stringa di query. Il codice verifica che il valore non sia vuoto e che sia un numero intero.

if(!IsPost){
    if(!Request.QueryString["classid"].IsEmpty() && Request.QueryString["classid"].IsInt()) {
        // Process the value
    }
    else{
        Validation.AddFormError("No class was selected.");
    }
}

Si noti che il test viene eseguito quando la richiesta non è un invio di modulo (if(!IsPost)). Questo test passerà la prima volta che viene richiesta la pagina, ma non quando la richiesta è un invio di modulo.

Per visualizzare questo errore, è possibile aggiungere l'errore all'elenco degli errori di convalida chiamando Validation.AddFormError("message"). Se la pagina contiene una chiamata al Html.ValidationSummary metodo , viene visualizzato l'errore, proprio come un errore di convalida dell'input dell'utente.

Risorse aggiuntive

Uso dei moduli HTML nei siti di Pagine Web ASP.NET