Validation en ASP.NET 2.0

Uno de los "tips" o "pijaditas" que más me ha atraído siempre la atención en ASP.NET son los validadores.

¿Cuántas veces os habéis tenido que currar un largo formulario donde exigíais ciertas condiciones en cada campo? Que si éste no puede estar vacío, que si este otro debe ser un mail, que si este otro debe ser un número mayor de 100 pero menor de 200... MUCHAS!!

En principio habías dos opciones, hacerlo con javascript o hacer la comprobación en servidor... o las dos cosas a la vez... pero eso daba un trabajo impresionante para un formulario medianamente largo... y no digamos nada si hablamos de cambios en ese formulario.

Pues bien, los ASPNETeros estamos de suerte, pues este tipo de cosillas son muy sencillas de implementar, sin más que arrastrar el ratón .

Durante este artículo veremos los diferentes controles web para validación de datos, y en el primero de ellos hablaremos de generalidades.

RequiredFieldValidator (y generalidades)
Personalmente es el validador que más uso y apuesto a que es el más común de todos en la web.NET. El concepto es muy sencillo: se asegura de que cierto control no esté vacío.

Pero vayamos primero con las generalidades. Aquí el concepto es que cuando el usuario provoca cierto evento (por ejemplo presiona un botón o selecciona un Item de una lista desplegable), nosotros queremos asegurarnos de que se cumplen ciertas reglas en nuestro formulario. Por ejemplo que un campo de texto no esté vacío:

    <asp:TextBox ID="TextBox1" runat="server" ValidationGroup="miPrueba"></asp:TextBox>
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TextBox1"
        ErrorMessage="Mensaje de error" ValidationGroup="miPrueba"></asp:RequiredFieldValidator>
    <asp:Button ID="Button1" runat="server" Text="Button" ValidationGroup="miPrueba"  OnClick="Button1_Click" />


 Estudiando el RequiredFieldValidator vemos que:
- ControlToValidate: desde aquí se asigna el control al que vamos a "vigilar" que no se quede vacío.
- ErrorMessage: obviamente es el mensaje de error. Puedes poner cosas como "Este campo no puede estar vacío" o simplemente un "*".
- ValidationGroup: esto es nuevo en ASP.NET 2.0, y define el grupo de controles que pertenecen a un grupo de validación. En ASP.NET 1.x no era así de modo que se validaban todos los controles de la página, por lo que no se podía tener 2 grupos independientes de TextBox + Button con validadores independientes, ya que si se validaba uno también se validaba otro. Como véis, ValidationGroup: también los tienen el resto de controles implicados.
- Cosas por defecto: el resto de cosillas por defecto las puede cambiar cada uno a su gusto. Por ejemplo, por defecto, el mensaje de error aparece en cursiva y en rojo, y también por defecto (y muy aconsejable) la validación se realiza en javascript, por lo que si encuentra algún error no hace falta ir al servidor.

Y esto de la validación en javascript es muy interesante y viene al hilo de que conviene exigir en servidor que los requisitos definidos con los Validadores se han cumplido. En cristiano, nuestro codebehind:

    protected void Button1_Click(object sender, EventArgs e)
    {
        Page.Validate("miPrueba");

        if (Page.IsValid)
        {
            // Realizar acciones
        }
    }


Cuando hacemos clic sobre el botón, validamos el grupo de validación que corresponda, y realizamos las acciones en caso de que el resultado sea válido. En nuestro ejemplo, daría válido si el TextBox1 no estuviera vacío.

RangeValidator
El RangeValidator se encarga de asegurar que el control que estemos validando esté dentro de cierto rango (). Lo que no es tan es que no sólo se trabaja con enteros, sino que se trabaja con strings, fechas, double y currency.

Para que nuestra TextBox2 tenga un número entre 10 y 100:    

<asp:RangeValidator ID="RangeValidator1" runat="server" ErrorMessage="Fuera de rango" ControlToValidate="TextBox2" MaximumValue="100" MinimumValue="10" Type="Integer" ValidationGroup="miPrueba"></asp:RangeValidator>

Donde todos los atributos se autoexplican.

CompareValidator
Con el comparevalidator, nos aseguramos de que dos controles tengan el mismo valor. El propio control Login de ASP.NET lo usa para asegurarse de que el "password" y "repite password" sean el mismo.

Para asegurarnos de que el TextBox3 y el TextBox4 sean iguales:

    <asp:CompareValidator ID="CompareValidator1" runat="server" ControlToCompare="TextBox4"
        ControlToValidate="TextBox3" ErrorMessage="No son iguales!!" ValidationGroup="miPrueba"></asp:CompareValidator>


Pero no sólo eso, el CompareValidator da la posibilidad de comparar un control con cualquier otra cosa mediante el atributo ValueToCompare.

Por ejemplo, y esto ya es imaginación pura y dura, podemos asegurarnos de que el TextBox3 sea igual al valor de cierta variable dentro del ViewState (o del queryString, o una variable de sesión...):

En codebehind:
        CompareValidator1.ValueToCompare = ViewState["nombreVariable"];

en .aspx:
    <asp:CompareValidator ID="CompareValidator1" runat="server" ControlToCompare="TextBox3"
        ErrorMessage="CompareValidator" ValidationGroup="miPrueba"></asp:CompareValidator>


RegularExpressionValidator
Y para validar CualquierCosaQueSeNosOcurra, ¿Qué mejor que una buena expresión regular?? (Os recomiendo que le echéis un vistazo pausadito a Expresiones regulares. Introducción. y a Expresiones regulares. Cómo trabajarlas con ASP.NET.).

Por ejemplo, con este código nos aseguramos que el TextBox5 sea un email:

    <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="TextBox5"
        ErrorMessage="No cumple la expresión regular" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
        ValidationGroup="miPrueba"></asp:RegularExpressionValidator>


CustomValidator
El colofón final de los validadores es cuando la validación es tan compleja (por ejemplo supone la combinación de varios controles a la vez) que sólo es posible validarla con una función específica.

Por ejemplo, vamos a hacer que una función que tenemos en servidor y que llamaremos "ValidameEnServidor", sea la que compruebe si se cumplen los requisitos que queremos:

Ejemplo_CustomValidator_Servidor.aspx
    <asp:CustomValidator ID="CustomValidator1" runat="server" OnServerValidate="ValidameEnServidor" EnableClientScript="false"
        ControlToValidate="TextBox6" ErrorMessage="No cumples la validación de servidor." ValidationGroup="miPrueba"></asp:CustomValidator>

Ejemplo_CustomValidator_Servidor.aspx.cs
    protected void ValidameEnServidor(object source, ServerValidateEventArgs value)
    {
       // Hacemos las comprobaciones que queramos con los controles que queramos,
       // y al final se le da un valor a:
       value.IsValid = true; // (o false)
    }


Fijaos que al CustomValidator le decimos que NO lo compruebe con javascript (EnableClientScript="false"), porque en nuestro ejemplo queremos que lo haga exclusivamente en servidor.

Sin embargo, la comprobación en javascript en muy sencilla, de modo que no tendríamos más que:

Ejemplo_CustomValidator_Cliente.aspx
    <asp:CustomValidator ID="CustomValidator1" runat="server" ClientValidationFunction="ValidameEnCliente"
        ControlToValidate="TextBox6" ErrorMessage="No cumples la validación de servidor." ValidationGroup="miPrueba"></asp:CustomValidator>

<script language="JavaScript">
<!--
  function
ValidameEnCliente(sender, args)
  {
       // Realizamos las comprobaciones que creamos necesarias para finalmente:
        args.IsValid = true; (o false);
  }
// -->
</script>



ValidationSummary
Como me gusta ASP.NET... y es que el equipo de ASP.NET ha pensado en todo!!
ValidationSummary lo único que hace es hacernos un pequeños resumen de los resultados de nuestra validación.

Por ejemplo, imaginemos que tenemos un enorme formulario con 15 DropDownList's y 20 TextBox's, y que entre el principio del formulario y el final hay que hacer rodar varias veces la ruedecita de nuestro ratón .

Además, nuestro botón de "Enviar información" está en la parte final... ¿Qué sucede si tenemos todos los campos bien, menos el primer TextBox (que está arriba del todo)? Pues sucede que el usuario se queda esperando, aprieta varias veces al botón y comprueba y recomprueba que el formulario no se envía al servidor - "Vaya xxxxxx de página", pensará nuestro usuario.

Pues para eso está el ValidationSummary. Nosotros lo pondremos cerquita de nuestro botón de "Enviar información" y allí aparecerán todos los fallos a la hora de rellenar datos que tenga nuestro formulario.

Esto ya funcionaría:

    <asp:ValidationSummary ID="ValidationSummary1" runat="server" ValidationGroup="miPrueba" />


¿Son o nos son maravillosos los Validators en ASP.NET 2.0?