Agregar controles de validación a la interfaz de edición de DataList (VB)

por Scott Mitchell

Descargar PDF

En este tutorial veremos lo fácil que es agregar controles de validación a EditItemTemplate de DataList para proporcionar una interfaz de usuario de edición infalible.

Introducción

En los tutoriales de edición de DataList hasta el momento, las interfaces de edición de DataLists no incluían ninguna validación proactiva de entrada de usuario, aunque una entrada de usuario no válida (como un nombre de producto que falta o un precio negativo) diera como resultado una excepción. En el tutorial anterior vimos cómo agregar código de control de excepciones al controlador de eventos UpdateCommand de DataList para detectar y mostrar correctamente información sobre las excepciones generadas. Lo ideal, sin embargo, es que la interfaz de edición incluya controles de validación para impedir desde el principio que un usuario escriba estos datos no válidos.

En este tutorial veremos lo fácil que es agregar controles de validación a EditItemTemplate de DataList para proporcionar una interfaz de usuario de edición infalible. En concreto, este tutorial sigue con el ejemplo creado en el tutorial anterior y mejora la interfaz de edición para incluir la validación adecuada.

Paso 1: Replicar el ejemplo de Controlar las excepciones de nivel BLL y DAL

En el tutorial Controlar las excepciones de nivel BLL y DAL creamos una página donde se enumeraban los nombres y precios de los productos en un objeto DataList editable de dos columnas. Nuestro objetivo en este tutorial es mejorar la interfaz de edición de DataList para que incluya controles de validación. En concreto, nuestra lógica de validación hará lo siguiente:

  • Requerir que se proporcione el nombre del producto
  • Garantizar que el valor de precio especificado tiene un formato de moneda válido
  • Garantizar que el valor de precio especificado es mayor o igual que cero, ya que un valor de UnitPrice negativo no es válido

Antes de pasar a ver cómo mejorar el ejemplo anterior para incluir validación, primero es necesario replicar el ejemplo de la página ErrorHandling.aspx de la carpeta EditDeleteDataList en la página de este tutorial, UIValidation.aspx. Para ello, es necesario copiar tanto el marcado declarativo como el código fuente de la página ErrorHandling.aspx. Copie primero el marcado declarativo del siguiente modo:

  1. Abra la página ErrorHandling.aspx en Visual Studio.
  2. Vaya al marcado declarativo de la página (haga clic en el botón Origen de la parte inferior de la página).
  3. Copie el texto dentro de las etiquetas <asp:Content> y </asp:Content> (líneas 3 a 32), como se muestra en la figura 1.

Copy the Text Within the <asp:Content> Control

Figura 2: Copia del texto dentro del control <asp:Content> (haga clic para ver la imagen a tamaño completo)

  1. Abra la página UIValidation.aspx.
  2. Vaya al marcado declarativo de la página.
  3. Pegue el texto dentro del control <asp:Content>.

Para copiar encima del código fuente, abra la página ErrorHandling.aspx.vb y copie solo el texto dentro de la clase EditDeleteDataList_ErrorHandling. Copie los tres controladores de eventos (Products_EditCommand, Products_CancelCommand y Products_UpdateCommand) junto con el método DisplayExceptionDetails, pero no copie la declaración de clase ni las instrucciones using. Pegue el texto copiado dentro de la clase EditDeleteDataList_UIValidation en UIValidation.aspx.vb.

Después de pasar el contenido y el código de ErrorHandling.aspx a UIValidation.aspx, dedique un momento a probar las páginas en un explorador. Debería aparecer la misma salida y experimentar la misma funcionalidad en cada una de estas dos páginas (vea la figura 2).

The UIValidation.aspx Page Mimics the Functionality in ErrorHandling.aspx

Figura 2: La página UIValidation.aspx imita la funcionalidad de ErrorHandling.aspx (haga clic para ver la imagen a tamaño completo)

Paso 2: Agregar controles de validación a EditItemTemplate de DataList

Al crear formularios de entrada de datos, es importante que los usuarios escriban los campos obligatorios y que todas sus entradas proporcionadas sean valores válidos y con un formato correcto. Para ayudar a garantizar que las entradas de un usuario son válidas, ASP.NET proporciona cinco controles de validación integrados diseñados para validar el valor de un único control web de entrada:

Para obtener más información sobre estos cinco controles, consulte el tutorial Agregar controles de validación a interfaces de edición e inserción o eche un vistazo a la sección Controles de validación de los tutoriales de inicio rápido de ASP.NET.

En nuestro tutorial, necesitaremos usar RequiredFieldValidator para asegurarnos de que se ha proporcionado un valor de nombre del producto y también usar CompareValidator para asegurarnos de que el precio especificado tiene un valor mayor o igual que 0 y presenta un formato de moneda válido.

Nota:

Aunque ASP.NET 1.x tenía estos mismos cinco controles de validación, ASP.NET 2.0 incorpora varias mejoras, las dos principales son la compatibilidad con scripts del lado cliente para exploradores además de Internet Explorer y la capacidad de particionar en grupos de validación los controles de validación de una página. Para obtener más información sobre las nuevas características de control de validación de la versión 2.0, consulte Disección de los controles de validación de ASP.NET 2.0.

Comencemos agregando los controles de validación necesarios a EditItemTemplate de DataList. Esta tarea se puede realizar a través del Diseñador, haciendo clic en el vínculo Editar plantillas de la etiqueta inteligente DataList, o bien a través de sintaxis declarativa. Vamos a recorrer paso a paso el proceso mediante la opción Editar plantillas de la vista Diseño. Después de elegir editar EditItemTemplate de DataList, agregue un elemento RequiredFieldValidator arrastrándolo desde el cuadro de herramientas a la interfaz de edición de plantillas y colocándolo después del TextBox ProductName.

Add a RequiredFieldValidator to the EditItemTemplate After the ProductName TextBox

Figura 3: Adición de un elemento RequiredFieldValidator a EditItemTemplate After después del TextBox ProductName (haga clic para ver la imagen a tamaño completo)

Todos los controles de validación funcionan validando la entrada de un solo control web de ASP.NET. Por lo tanto, es necesario indicar que el elemento RequiredFieldValidator que acabamos de agregar debe validarse contrastándolo con el TextBoxProductName; esto se hace estableciendo la propiedad ControlToValidate del control de validación en el ID de la propiedad del control web adecuado (ProductName, en este caso). A continuación, establezca la propiedad ErrorMessage en Debe proporcionar el nombre del producto y la propiedad Text en *. El valor de la propiedad Text, si se proporciona, es el texto que muestra el control de validación si se produce un error en la validación. El valor de la propiedad ErrorMessage, que es obligatorio, lo usa el control ValidationSummary; si se omite el valor de la propiedad Text, el control de validación muestra el valor de la propiedad ErrorMessage en la entrada no válida.

Después de establecer estas tres propiedades de RequiredFieldValidator, la pantalla debe ser similar a la de la figura 4.

Set the RequiredFieldValidator s ControlToValidate, ErrorMessage, and Text Properties

Figura 4: Establecimiento de las propiedades ControlToValidate, ErrorMessage y Text de RequiredFieldValidator (haga clic para ver la imagen a tamaño completo)

Con RequiredFieldValidator agregado a EditItemTemplate, lo único que queda es agregar la validación necesaria para al TextBox de precio del producto. Dado que UnitPrice es opcional al editar un registro, no es necesario agregar un elemento RequiredFieldValidator. Sin embargo, es necesario agregar un elemento CompareValidator para asegurarnos de que UnitPrice, si se proporciona, tiene el formato de moneda correcto y es mayor o igual que 0.

Agregue el elemento CompareValidator a EditItemTemplate y establezca su propiedad ControlToValidate en UnitPrice, su propiedad ErrorMessage en El precio debe ser mayor o igual que cero y no puede incluir el símbolo de moneda y, por último, su propiedad Text en *. Para indicar que el valor UnitPrice debe ser mayor o igual que 0, establezca la propiedad Operator de CompareValidator en GreaterThanEqual, su propiedad ValueToCompare en 0 y su propiedad Type en Currency.

Después de agregar estos dos controles de validación, la sintaxis declarativa de EditItemTemplate de DataList debe ser similar a la siguiente:

<EditItemTemplate>
    Product name:
        <asp:TextBox ID="ProductName" runat="server"
            Text='<%# Eval("ProductName") %>'></asp:TextBox>
        <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
            ControlToValidate="ProductName"
            ErrorMessage="You must provide the product's name"
            runat="server">*</asp:RequiredFieldValidator>
    <br />
    Price:
        <asp:TextBox ID="UnitPrice" runat="server"
            Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:TextBox>
        <asp:CompareValidator ID="CompareValidator1"
            ControlToValidate="UnitPrice"
            ErrorMessage="The price must be greater than or equal to zero
                          and cannot include the currency symbol"
            Operator="GreaterThanEqual" Type="Currency" ValueToCompare="0"
            runat="server">*</asp:CompareValidator><br />
    <br />
    <asp:Button ID="UpdateProduct" runat="server" CommandName="Update"
        Text="Update" /> 
    <asp:Button ID="CancelUpdate" runat="server" CommandName="Cancel"
        Text="Cancel" />
</EditItemTemplate>

Después de realizar estos cambios, abra la página en un explorador. Si intenta omitir el nombre o escribir un valor de precio no válido al editar un producto, aparece un asterisco junto al cuadro de texto. Como se muestra en la figura 5, un valor de precio que incluye el símbolo de moneda (como 19,95 $) se considera no válido. CurrencyType de CompareValidator permite el uso de separadores de dígitos (como comas o puntos, dependiendo de la configuración cultural) y de un signo más o menos inicial, pero no permite usar símbolos de moneda. Este comportamiento puede desconcertar a los usuarios, ya que la interfaz de edición presenta UnitPrice actualmente usando un formato de moneda.

An Asterisk Appears Next to the Textboxes with Invalid Input

Figura 5: Aparece un asterisco junto a los cuadros de texto con entradas no válidas (haga clic para ver la imagen a tamaño completo)

Aunque la validación funciona tal cual, el usuario tiene que quitar manualmente el símbolo de moneda al editar un registro, lo cual no es aceptable. Además, si hay entradas no válidas en la interfaz de edición, ni los botones Actualizar ni Cancelar, al hacer clic en ellos, invocarán un postback. Lo ideal es que el botón Cancelar devuelva DataList a su estado de edición previa, independientemente de la validez de las entradas del usuario. Además, es necesario asegurarnos de que los datos de la página sean válidos antes de actualizar la información del producto en el controlador de eventos UpdateCommand de DataList, ya que los usuarios cuyos exploradores no admitan JavaScript o que tengan la compatibilidad con ellos deshabilitada pueden omitir la lógica de cliente de los controles de validación.

Quitar el símbolo de moneda del TextBox UnitPrice de EditItemTemplate

Al usar Currency``Type de CompareValidator, la entrada que se va a validar no debe incluir ningún símbolo de moneda. La presencia de estos símbolos hace que CompareValidator marque la entrada como no válida. Sin embargo, nuestra interfaz de edición incluye actualmente un símbolo de moneda en el TextBox UnitPrice, lo que significa que el usuario debe quitar explícitamente el símbolo de moneda antes de guardar los cambios. Para solucionar esto, tenemos tres opciones:

  1. Configurar EditItemTemplate para que el valor del TextBox UnitPrice no tenga formato de moneda.
  2. Permitir al usuario escribir un símbolo de moneda quitando el elemento CompareValidator y reemplazándolo por un elemento RegularExpressionValidator que compruebe si hay un valor de moneda con el formato correcto. El reto aquí es que la expresión regular para validar un valor de moneda no es tan sencillo como con CompareValidator, y requeriría escribir código si quisiéramos incorporar la configuración de referencia cultural.
  3. Quitar el control de validación por completo y básese en la lógica de validación del servidor personalizada del controlador de eventos RowUpdating de GridView.

Quedémonos con la opción 1 en este tutorial. Actualmente, UnitPrice tiene el formato de un valor de moneda debido a la expresión de enlace de datos del TextBox en EditItemTemplate: <%# Eval("UnitPrice", "{0:c}") %>. Cambie la instrucción Eval a Eval("UnitPrice", "{0:n2}"), que da formato al resultado como un número con dos dígitos de precisión. Esto se puede hacer directamente a través de sintaxis declarativa o haciendo clic en el vínculo para editar DataBindings del TextBox UnitPrice en EditItemTemplate de DataList.

Con este cambio, el precio con formato en la interfaz de edición incluye la coma como separador de grupo y el punto como separador decimal, pero deja el símbolo de moneda.

Nota:

Al quitar el formato de moneda de la interfaz editable, resulta útil colocar el símbolo de moneda como texto fuera del TextBox. Esto da una pista al usuario de que no es necesario proporcionar el símbolo de moneda.

Arreglar el botón Cancelar

Los controles web de validación emiten JavaScript de forma predeterminada para realizar la validación en el lado cliente. Cuando se hace clic en algún control Button, LinkButton o ImageButton, los controles de validación de la página se comprueban en el lado cliente antes de que se produzca el postback. Si hay datos no válidos, el postback se cancela. Sin embargo, en algunos controles Button, la validez de los datos puede ser irrelevante, con lo cual la cancelación del postback debido a la presencia de datos no válidos es una molestia.

El botón Cancelar es un ejemplo de este tipo. Imagine que un usuario escribe datos no válidos, como omitir el nombre del producto y, a continuación, decide que no quiere guardar el producto y presiona el botón Cancelar. Actualmente, el botón Cancelar activa los controles de validación de la página, que notifican que falta el nombre del producto e impiden el postback. El usuario tendrá que escribir texto en el TextBox ProductName exclusivamente para cancelar el proceso de edición.

Por suerte, Button, LinkButton e ImageButton tienen una propiedad CausesValidation que puede indicar si el botón debe iniciar o no la lógica de validación (el valor predeterminado es True). Establezca la propiedad CausesValidation del botón Cancelar en False.

Asegurarse de que las entradas son válidas en el controlador de eventos UpdateCommand

Debido al script del lado cliente emitido por los controles de validación, si un usuario escribe una entrada no válida, los controles de validación cancelan los postbacks iniciados por los controles Button, LinkButton o ImageButton cuyas propiedades CausesValidation son True (el valor predeterminado). Sin embargo, si un usuario visita con un explorador antiguo o uno cuya compatibilidad con JavaScript se ha deshabilitado, las comprobaciones de validación del lado cliente no se ejecutarán.

Todos los controles de validación de ASP.NET repiten su lógica de validación inmediatamente después del postback, y notifican la validez general de las entradas de la página a través de la propiedad Page.IsValid. Sin embargo, el flujo de página no se interrumpe ni se detiene de ninguna manera en función del valor de Page.IsValid. Como desarrolladores, es nuestra responsabilidad asegurarnos de que la propiedad Page.IsValid tiene un valor de True antes de continuar con el código que da por hecho que los datos de entrada son válidos.

Si un usuario tiene JavaScript deshabilitado, visita nuestra página, edita un producto, escribe un valor de precio demasiado caro y hace clic en el botón Actualizar, se omitirá la validación del lado cliente y se producirá un postback. En un postback, se ejecuta el controlador de eventos UpdateCommand de la página ASP.NET y se produce una excepción al intentar analizar Demasiado caro para un Decimal. Puesto que tenemos control de excepciones, esta excepción se controlará correctamente, pero podríamos evitar que los datos no válidos se cuelen simplemente procediendo con el controlador de eventos UpdateCommand si Page.IsValid tiene un valor de True.

Agregue el código siguiente al inicio del controlador de eventos UpdateCommand, inmediatamente antes del bloque Try:

If Not Page.IsValid Then
    Exit Sub
End If

Con esta adición, el producto intentará actualizarse solo si los datos enviados son válidos. La mayoría de los usuarios no podrá realizar postback de los datos no válidos debido a los scripts del lado cliente de los controles de validación, pero los usuarios cuyos exploradores no admitan JavaScript o que tienen deshabilitada la compatibilidad con JavaScript pueden omitir las comprobaciones del lado cliente y enviar datos no válidos.

Nota:

El lector sagaz recordará que, al actualizar datos con GridView, no era necesario comprobar explícitamente la propiedad Page.IsValid en la clase de código subyacente de nuestra página. Esto se debe a que GridView consulta la propiedad Page.IsValid de forma automática, y procederá a la actualización únicamente si se devuelve un valor de True.

Paso 3: Resumen de problemas de entrada de datos

Además de los cinco controles de validación, ASP.NET incluye el control ValidationSummary, que muestra los ErrorMessage de esos controles de validación que detectaron datos no válidos. Estos datos de resumen se pueden mostrar como texto en la página web o a través de un cuadro de mensaje modal del lado cliente. Vamos a mejorar este tutorial para incluir un cuadro de mensajes del lado cliente que resuma los problemas de validación.

Para ello, arrastre un control ValidationSummary desde el cuadro de herramientas al Diseñador. La ubicación del control ValidationSummary no importa, ya que vamos a configurarlo para que solo muestre el resumen como un cuadro de mensaje. Después de agregar el control, establezca su propiedad ShowSummary en False y su propiedad ShowMessageBox en True. Con esta adición, los errores de validación se resumen en un cuadro de mensaje del lado cliente (vea la figura 6).

The Validation Errors are Summarized in a Client-Side Messagebox

Figura 6: Los errores de validación se resumen en un cuadro de mensaje del lado cliente (haga clic para ver la imagen a tamaño completo)

Resumen

En este tutorial, hemos visto cómo reducir la probabilidad de que se muestren excepciones mediante el uso de controles de validación para garantizar que las entradas de los usuarios son válidas antes de intentar usarlas en el flujo de trabajo de actualización. ASP.NET proporciona cinco controles web de validación diseñados para inspeccionar una entrada de control web determinada e informar de la validez de la entrada. En este tutorial, hemos usado dos de esos cinco controles, RequiredFieldValidator y CompareValidator, para garantizar que se proporciona el nombre del producto y que el precio tiene un formato de moneda con un valor mayor o igual que cero.

Agregar controles de validación a la interfaz de edición de DataList es tan sencillo como arrastrarlos a EditItemTemplate desde el cuadro de herramientas y establecer una serie de propiedades. De forma predeterminada, los controles de validación emiten automáticamente el script de validación del lado cliente; también proporcionan validación del lado servidor en los postbacks, almacenando el resultado acumulado en la propiedad Page.IsValid. Para omitir la validación del lado cliente cuando se hace clic en un control Button, LinkButton o ImageButton, establezca la propiedad CausesValidation del botón en False. Asimismo, antes de realizar cualquier tarea con los datos enviados en el postback, asegúrese de que la propiedad Page.IsValid devuelve True.

Todos los tutoriales de edición de DataList que hemos examinado hasta ahora han tenido interfaces de edición muy sencillas: un TextBox para el nombre del producto y otro para el precio. Sin embargo, la interfaz de edición puede contener una combinación de diferentes controles web, como DropDownLists, Calendars, RadioButtons, CheckBoxes, etc. En el siguiente tutorial, veremos cómo crear una interfaz que use una variedad de controles web.

¡Feliz programación!

Acerca del autor

Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Puede ponerse en contacto con él a través de mitchell@4GuysFromRolla.com. o a través de su blog, que se puede encontrar en http://ScottOnWriting.NET.

Agradecimientos especiales a

Muchos revisores han evaluado esta serie de tutoriales. Los revisores principales de este tutorial han sido Dennis Patterson, Ken Pespisa y Liz Shulok. ¿Le interesa revisar mis próximos artículos de MSDN? Si es así, escríbame a mitchell@4GuysFromRolla.com.