Validar la entrada del usuario en los sitios de ASP.NET Web Pages (Razor)

de Tom FitzMacken

En este artículo se describe cómo validar la información que obtiene de los usuarios, es decir, cómo se asegura de que los usuarios escriban información válida en formularios HTML en un sitio ASP.NET Web Pages (Razor).

Temas que se abordarán:

  • Cómo comprobar que la entrada de un usuario coincide con los criterios de validación que defina.
  • Cómo determinar si se han superado todas las pruebas de validación.
  • Cómo mostrar los errores de validación (y cómo darles formato).
  • Cómo validar los datos que no proceden directamente de los usuarios.

Estos son los conceptos de programación ASP.NET presentados en el artículo:

  • El asistente Validation.
  • Los métodos Html.ValidationSummary y Html.ValidationMessage.

Versiones de software usadas en el tutorial

  • ASP.NET Web Pages (Razor) 3

Este tutorial también funciona con ASP.NET Web Pages 2.

Este artículo contiene las siguientes secciones:

Información general sobre la validación de entrada de usuario

Si pide a los usuarios que escriban información en una página (por ejemplo, en un formulario), es importante asegurarse de que los valores que especifican son válidos. Por ejemplo, no desea procesar un formulario en el que falte información crítica.

Cuando los usuarios escriben valores en un formulario HTML, los valores que escriben son cadenas. En muchos casos, los valores que necesita son otro tipos de datos, como enteros o fechas. Por lo tanto, también debe asegurarse de que los valores que escriben los usuarios se pueden convertir correctamente en los tipos de datos adecuados.

También puede tener ciertas restricciones en los valores. Incluso si los usuarios escriben correctamente un entero, por ejemplo, es posible que tenga que asegurarse de que el valor se encuentra dentro de un rango determinado.

Screenshot shows Validation errors that use CSS style classes.

Nota:

Importante La validación de la entrada del usuario también es importante para la seguridad. Al restringir los valores que los usuarios pueden escribir en formularios, reduce la posibilidad de que alguien pueda escribir un valor que pueda poner en peligro la seguridad del sitio.

Validar los datos introducidos por el usuario

En ASP.NET Web Pages 2, puede usar el asistente Validator para probar la entrada del usuario. El enfoque básico es hacer lo siguiente:

  1. Determine qué elementos de entrada (campos) desea validar.

    Normalmente se validan valores en elementos <input> de un formulario. Sin embargo, es recomendable validar toda la entrada, incluso la entrada procedente de un elemento restringido, como una lista <select>. Esto ayuda a asegurarse de que los usuarios no omitan los controles de una página y envíen un formulario.

  2. En el código de página, agregue comprobaciones de validación individuales para cada elemento de entrada mediante métodos del asistente Validation.

    Para comprobar los campos obligatorios, use Validation.RequireField(field, [error message]) (para un campo individual) o Validation.RequireFields(field1, field2, ...)) (para una lista de campos). Para otros tipos de validación, use Validation.Add(field, ValidationType). Para ValidationType, puede usar estas opciones:

    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. Cuando se envíe la página, compruebe si se ha superado la validación comprobando Validation.IsValid:

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

    Si hay algún error de validación, omita el procesamiento normal de páginas. Por ejemplo, si el propósito de la página es actualizar una base de datos, no lo hace hasta que se corrijan todos los errores de validación.

  4. Si hay errores de validación, muestre los mensajes de error en el marcado de la página mediante Html.ValidationSummary o Html.ValidationMessage o ambos.

En el ejemplo siguiente se muestra una página que ilustra estos pasos.

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

Para ver cómo funciona la validación, ejecute esta página y realice errores deliberadamente. Por ejemplo, este es el aspecto de la página si olvida escribir un nombre de curso, si escribe an y si escribe una fecha no válida:

Validation errors in the rendered page

Agregar la validación del lado cliente

De forma predeterminada, la entrada del usuario se valida después de que los usuarios envíen la página; es decir, la validación se realiza en el código del servidor. Una desventaja de este enfoque es que los usuarios no saben que han realizado un error hasta después de enviar la página. Si un formulario es largo o complejo, notificar errores solo después de enviar la página puede ser inconveniente para el usuario.

Puede agregar compatibilidad para realizar la validación en el script de cliente. En ese caso, la validación se realiza a medida que los usuarios trabajan en el explorador. Por ejemplo, supongamos que especifica que un valor debe ser un entero. Si un usuario escribe un valor no entero, el error se notifica en cuanto el usuario deja el campo de entrada. Los usuarios reciben comentarios inmediatos, lo cual resulta conveniente. La validación basada en cliente también puede reducir el número de veces que el usuario tiene que enviar el formulario para corregir varios errores.

Nota:

Incluso si usa la validación del lado cliente, la validación siempre se realiza en el código del servidor. Realizar la validación en el código de servidor es una medida de seguridad, en caso de que los usuarios omitan la validación basada en el cliente.

  1. Registre las siguientes bibliotecas de JavaScript en la página:

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

    Dos de las bibliotecas se pueden cargar desde una red de entrega de contenido (CDN), por lo que no es necesario tenerlas en el equipo o servidor. Sin embargo, debe tener una copia local de jquery.validate.unobtrusive.js. Si aún no está trabajando con una plantilla de WebMatrix (como elsitio de inicio) que incluye la biblioteca, cree un sitio de páginas web basado en el sitio de inicio. A continuación, copie el archivo .js en el sitio actual.

  2. En el marcado, para cada elemento que valida, agregue una llamada a Validation.For(field). Este método emite atributos que se usan en la validación del lado cliente. (En lugar de emitir código JavaScript real, el método emite atributos como data-val-.... Estos atributos admiten la validación de cliente discreta que usa jQuery para realizar el trabajo).

En la página siguiente se muestra cómo agregar características de validación de cliente al ejemplo mostrado anteriormente.

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

No todas las comprobaciones de validación se ejecutan en el cliente. En concreto, la validación de tipo de datos (entero, fecha, etc.) no se ejecuta en el cliente. Las siguientes comprobaciones funcionan tanto en el cliente como en el servidor:

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

En este ejemplo, la prueba de una fecha válida no funcionará en el código de cliente. Sin embargo, la prueba se realizará en el código del servidor.

Formato en errores de validación

Puede controlar cómo se muestran los errores de validación mediante la definición de clases CSS que tienen los siguientes nombres reservados:

  • field-validation-error. Define la salida del método Html.ValidationMessage cuando se muestra un error.
  • field-validation-valid. Define la salida del método Html.ValidationMessage cuando no hay ningún error.
  • input-validation-error. Define cómo se representan los elementos <input> cuando se produce un error. (Por ejemplo, puede usar esta clase para establecer el color de fondo de un elemento <> en un color diferente si su valor no es válido). Esta clase CSS solo se usa durante la validación del cliente (en ASP.NET Web Pages 2).
  • input-validation-valid. Define la apariencia de los elementos <input> cuando no hay ningún error.
  • validation-summary-errors. Define la salida del método Html.ValidationSummary que muestra una lista de errores.
  • validation-summary-valid. Define la salida del método Html.ValidationSummary cuando no hay ningún error.

En el bloque siguiente <style> se muestran reglas para las condiciones de error.

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

Si incluye este bloque de estilo en las páginas de ejemplo anteriores del artículo, la presentación del error será similar a la siguiente ilustración:

Validation errors that use CSS style classes

Nota:

Si no usa la validación de cliente en ASP.NET Web Pages 2, las clases CSS para los elementos <input> (input-validation-error y input-validation-valid no tienen ningún efecto).

Presentación de errores estáticos y dinámicos

Las reglas CSS vienen en pares, como validation-summary-errors y validation-summary-valid. Estos pares le permiten definir reglas para ambas condiciones: una condición de error y una condición "normal" (no error). Es importante comprender que el marcado de la presentación de errores siempre se representa, incluso si no hay errores. Por ejemplo, si una página tiene un método Html.ValidationSummaryen el marcado, el origen de la página contendrá el marcado siguiente incluso cuando la página se solicite por primera vez:

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

En otras palabras, el método Html.ValidationSummary siempre representa un elemento <div> y una lista, incluso si la lista de errores está vacía. Del mismo modo, el método Html.ValidationMessage siempre representa un elemento <span> como marcador de posición para un error de campo individual, incluso si no hay ningún error.

En algunas situaciones, mostrar un mensaje de error puede hacer que la página se vuelva a enviar y puede hacer que los elementos de la página se muevan. Las reglas CSS que terminan en -valid le permiten definir un diseño que pueda ayudar a evitar este problema. Por ejemplo, puede definir field-validation-error y field-validation-valid para tener el mismo tamaño fijo. De este modo, el área de visualización del campo es estática y no cambiará el flujo de página si se muestra un mensaje de error.

Cómo validar los datos que no proceden directamente de los usuarios

A veces, tiene que validar la información que no procede directamente de un formulario HTML. Un ejemplo típico es una página en la que se pasa un valor en una cadena de consulta, como en el ejemplo siguiente:

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

En este caso, quiere asegurarse de que el valor que se pasa a la página (aquí, 1022 para el valor de classid) es válido. No puede usar directamente el asistente Validation para realizar esta validación. Sin embargo, puede usar otras características del sistema de validación, como la capacidad de mostrar mensajes de error de validación.

Nota:

Importante Valide siempre los valores que obtenga de cualquier origen , incluidos los valores de campo de formulario, los valores de cadena de consulta y los valores de cookie. Es fácil que las personas cambien estos valores (quizás con fines malintencionados). Por lo tanto, debe comprobar estos valores para proteger la aplicación.

En el ejemplo siguiente se muestra cómo se puede validar un valor que se pasa en una cadena de consulta. El código comprueba que el valor no está vacío y que es un entero.

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

Observe que la prueba se realiza cuando la solicitud no es un envío de formulario (if(!IsPost)). Esta prueba superaría la primera vez que se solicita la página, pero no cuando la solicitud es un envío de formulario.

Para mostrar este error, puede agregar el error a la lista de errores de validación llamando a Validation.AddFormError("message"). Si la página contiene una llamada al método Html.ValidationSummary, el error se muestra allí, al igual que un error de validación de entrada de usuario.

Recursos adicionales

Trabajar con formularios HTML en sitios de ASP.NET Web Pages