HTML limpio con ASP.NET 4 Web Forms

Este es el decimosexto post de la serie que estoy haciendo sobre VS 2010 y .NET 4.

El post de hoy es el primero sobre una serie que haré sobre algunos de los cambios más importantes que hemos hecho para que los Web Forms en ASP.NET 4 generen un HTML más limpio, que se acerce más al estándar y más amigable para las CSS. Hoy veremos lo que hemos hecho para controlar los atributos "ID" que se mandan al cliente.

Además de en el blog podéis seguir a scott en twitter: twitter.com/scottgu

HTML limpio, stándar, amigable a CSS

Uno de los problemas que los desarrolladores suelen tener con ASP.NET Web Forms es que cuando usan controles de servidor, no tienen la habilidad de generar fácilmente un markup limpio y amigable a CSS. Algunas quejas comunes a versiones anteriores de ASP.NET INCLUYEN:

  • Generación de atributos ID automáticos en el HTML que hacen difícil escribir JavaScript y CSS's.
  • Usar tablas en lugar de controles (en particular el control asp:menu) que hacen que el estilo sea horroroso.
  • Algunos controles renderizan propiedades inline incluso aunque se indique que no tienen estilo.
  • El ViewState puede ser más grande que el ideal.

ASP.NET 4 ofrece un mejor soporte para crear páginas que cumplan los estándares de forma predeterminada. El control <asp:> de ASP.NET 4 genera un HTML más limpio y con soporte para CSS - y ayuda a resolver los anteriores problemas.

Compatibilidad del lenguaje de Markup para actualizar aplicaciones ASP.NET Web Forms existentes

Una pregunta común cuando oyen que el Markup es más limpio es: "Genial, pero ¿qué pasa con las aplicaciones existenes? ¿Afectarán estos cambios cuando actualicemos nuestras aplicaciones?

Para asegurarnos de que no se producen este tipo de incidencias hemos habilitado un flag de condiguración - controlRenderingCompatibilityVersion- en el web.config que os permitirá decidir si queréis usar el nuevo markup más limpio de ASP.NET 4, o renderizar el mismo HTML que las versiones anteriores de ASP.NET:

Cuando el flag controlRenderingCompatibilityVersion  está puesto en "3.5" vuestras aplicaciones y controles de servidor se renderizarán usando el mismo sistema de generación de VS 2008 y .NET 3.5. Cuando está puesto en "4.0" vuestros controles y aplicación cumplirán estríctamente la especificación XHML 1.1, teniendo ids de cliente limpios, renderizado con corrección semántica en mente, y eliminando codigo inline extraño.

Este flag está configurado en 4.0 por defecto cuando se crea una nueva aplicación ASP.NET 4. Cualquier versión anterior que se actualice con VS 2010 tendrá este flag en "3.5" para asegurar la compatibilidad hacia atrás. Podéis cambiarlo (tanto a nivel de la aplicación, o en el web.config de cada página o a nivel de directorio) si cambiais vuestras páginas para que usen CSS y las nuevas características de renderizado.

Tema del día: Ids de cliente

La habilidad de tener ids predecibles en los elementos HTML renderizados es algo que los desarrolladores han pedido desde siempre en Web Forms (ids del tipo "ctl00_ContentPlaceholder1_ListView1_ctrl0_Label1 no han sido nunca muy populares). Poder controlar estos valores permiten escribir código JavaScript en el cliente de manera mucho más sencilla, haciendo más facil poder aplicar estilos con CSS, y en páiginas grandes pueden ayudar a reducir el tamaño del HTML generado.

Nueva propiedad ClientIDMode en los controles

ASP.NET 4 soporta la nueva propiedad ClientIDMode en la clase base Control. Esta propiedad indica cómo se deben generar los IDs de cliente cuando se renderizan. Esta propiedad soporta cuatro posibles valores:

  • AutoID: Renderiza la salida como en .NET 3.5 (IDs autogenerados que siguen poniendo prefijos como ctrl00 por compatibilidad.
  • Predictable(Por defecto): Elimina cualquier "ctl00" y si un control contiene otros, los sustituye con los de sus jijos (ejemplo: id="ParntControl_ChildControl")
  • Static - Deja en manos del desarrollador el nombre que se le asignará - por ejemplo: id="JustMyId")
  • Inherit- Le dice al control que delege el comportamiento de nombrado en el control que lo contenga.

La propiedad clientIdMode se puede establecer individualmente en los controles (o en los controles contenedores - en ese caso los controles incluidos heredarán esta propiedad):

O puede ser establecida en una página o a nivel del user control (usando las directivas <%@ Page %> o <%@ Control%>) - en ese caso los controles de las páginas o los user control heredarán ese valor (y pueden sobreescribirlo también):

O podemos indicarlo en el web.config de una aplicación - en ese caso las páginas de la aplicación usarán ese valor (y pueden sobreescribirlo):

Esto nos da la flexibilidad de personalizar el comportamiento de nombrado como queramos.

Ejemplo: Uso de la propiedad ClientIDMode para controlar los IDs de controles Non-List

Vamos a ver cómo podemos usar la propiedad ClientIDMode para controlar el renderizado de los elementos "ID" de una página. Para ayudarnos a ilustrar esto podemos crear una página simple llamada "SingleControlExample.aspx" basada en una master-page llamada "Site.Master", y que tan sólo contiene un control <asp:label> con el ID "Message" que contiene un contenedor <asp:content> llamado "MainContent":

En nuestro código trasero añadimos un simple código como el siguiente que genera dinámicamente la propiedad Text del label en tiempo de ejecución:

Si ejecutamos esta página con ASP.NET 3.5 ( o si tuviésemos configurada la aplícación ASP.NET 4 para que use el renderizado de la versión 3.5 o ClientIDMode=AutoID), obtendríamos el markup en cliente siguiente:

El ID es único (lo que es bueno) - pero un poco feo por el prefijo "ct100" (lo que es malo).

Renderizado usando ASP.NET 4 y la propiedad ClientIdMode en "Predictable"

Los controles de servidor en ASP.NET 4 por defecto generan sus IDs usando la propiedad ClientIDMode="Predictable". De esta manera se asegura una generacion de IDs únicos y que no van a crear conflictos en la página, pero a la vez hace que los IDs sean menos detallados y más predecibles. Esto significa que el markup generado de nuestro control <asp:label> se traducirá con ASP.NET 4 en:

Fijáos que ha desaparecido el prefijo "ct100". Como el control Message está dentro del contenedor "Maincontent", por defecto el ID se prefijará "MainContent_Message" para evitar posibles colisiones con otros controles de la página.

Renderizado usando ASP.NET 4 y la propiedad ClientIdMode en "Static"

Algunas veces no queremos que los valores IDs de nuestros controles se generen de forma gerárquica, sino que queremos renderizar unos IDs con el valor que nosotros queramos. Para poder hacer esto podemos usar la propiedad ClientIDMode=static, en este caso el ID se generará exáctamente igual  al que le indicamos en el nombre del control. Esto generará el siguiente markup en ASP.NET 4:

Esta opción nos permite tener control total sobre el ID que se generarán en nuestros controles.

Ejemplo: Uso de la propiedad ClientIDmode para controlar los IDs de los controles List enlazados a datos.

Los contorles lista enlazados a datos han sido históricamente los que han sido más complejos de estilizar/usar cuando trabajamos con Web Forms que generan IDs automáticamente. Ahora veremos un escenario en el que personalizaremos la generación de Ids usando un control ListView en ASP.NET 4

El siguiente código muestra un ejemplo de un ListView que muestra el contenido de una colección enlazada - en este caso, aeropuertos:

Ahora podemos escribir el siguiente código que rellena dinámicacmente la lista con los aeropuertos:

En tiempo de ejecución obtendríamos una lista con <ul> de los areopuertos. Fijáos que como lso elementos <ul> y <li> del template del ListView no son server controls, no se renderizan IDs en el markup:

Añadir IDs de cliente a cada elemento de fila

Ahora, vamos a decir que queremos añadir un ID de cliente a cada elemento de la lista para que podamos acceder a cada elemento programáticamente a través de JavaScript. Queremos que esos IDs sean únicos, predecibles e identificables.

Una primera aproximación será marcar cada elemento <li> con el template como si fuese un control de servidor (usando la propiedad runat=server) y dándole a cada uno  el id "airport":

Por defecto en ASP.NET 4 ser renderízará con IDs limpias:

Uso de la propiedad ClientIDRowSuffix

Nuestra plantilla genera IDs únicos para cada elemento <li> - pero si vamos a acceder a ellos programáticamente en el cliente con JavaScript querremos tener el ID que contienen el código del aeropuerto para que sea más sencillo referenciarlo. Las buenas noticias son que podemos conseguir esto de forma sencilla aprovechando la propiedad ClientIDRow Suffix en los controles enalzados a datos en ASP.NET 4 para tener un mayor control sobre las filas.

Para ello, estableceremos la propiedad ClientIDRowSuffix en "Code" en el control ListView. De esta manera le decimos al control ListView que use la propiedad enlazada "Code" de nuestra clase Airport cuando genere el ID:

Y ahora, en vez de tener sufijos para las filas como "1", "2" y "3", tendremos el valor Airport.Code embebido en los IDs (ej: _CLE, _CAK, _PDX, etc):

Podemos usar la propiedad ClientIDRowSuffix con otros controles enlazados a datos como el GridView. Es muy útil si queremos programar elementos de filas en el cliente - y udar IDs limpios para referenciarlos desde el código JavaScript.

Resúmen.

ASP.NET 4 nos permite generar un HTML mucho más limpio para nuestros controles de servidor en nuestras aplicaicones Web Forms.

En el post de hoy hemos visto cómo podemos controlar fácilmente los valores IDs que renderizan los controles de servidor. En próximos post veremos algunas de otras mejoras sobre el HTML generado de ASP.NET 4.

Espero que sirva,

Scott.

Traducido por: Juan María Laó Ramos.

Artículo original.

Un pensamiento en “HTML limpio con ASP.NET 4 Web Forms

Deja un comentario