ASP.NET 5 Introducción a los TagHelpers

Nota: Este post ha sido realizado con versiones previas de ASP.NET 5 y de Visual Studio 2015, lo aquí escrito puede variar con versiones  finales de la plataforma.

Los TagHelpers son una de las novedades más interesantes de MVC6. En cierto modo vienen a sustituir a los helpers Razor tradicionales, pero con un enfoque que puede recordar a los WebControls de Webforms, pero como veremos hay muchas diferencias entre los WebControls y los TagHelpers. Lo que nos permiten es podernos crear nuestras propias etiquetas HTML pero que serán procesadas por Razor (generando pues HTML que es el que será enviado al cliente).

Empecemos por lo más básico. Para crear un TagHelper nos basta con crear una clase que herede la clase TagHelper y redefinir el método Process. En dicho método debemos generar el HTML de salida necesario:

[snippet id=”197″]

Se puede observar el uso del atributo [ContentBehavior] con el valor Replace indicando que este TagHelper reemplazará el contenido que tenga en la vista por el que él genere. Luego veremos otras opciones para dicho atributo.

Una vez hemos creado un TagHelper el siguiente punto es utilizarlo. Para ello debemos importarlo en la vista utilizando la directiva @addtaghelper. Dicha directiva espera el nombre de un ensamblado y todos los TagHelpers definidos en dicho ensamblado son importados. Finalmente se usa una convención basada en el nombre de la clase para asignar una etiqueta a dicho TagHelper: dado que nuestra clase se llama DemoTagHelper, la etiqueta que debemos usar es <demo>:

[snippet id=”198″]

Los TagHelpers pueden recibir parámetros a través de atributos en la etiqueta HTML y que se mapean a propiedades en la clase que implementa el TagHelper:

[snippet id=”199″]

Y su uso quedaría como:

[snippet id=”200″]

Como se ha dicho antes un TagHelper no está obligado siempre a proporcionar todo su contenido, puede modificar el contenido que reciba del tag HTML que lo representa en la vista. Para ello se debe decorar la clase con el atributo [ContentBehavior] con el valor correspondiente:

  • None: El TagHelper no modifica el contenido (tan solo puede reemplazar la etiqueta HTML).
  • Prepend: El TagHelper puede añadir contenido antes del contenido que tenga su etiqueta HTML
  • Modify: El TagHelper puede modificar el contenido recibido en su etiqueta HTML
  • Replace: El TagHelper debe reemplazar el contenido recibido en su etiqueta HTML.

La posibilidad de que los TagHelpers exploren y modifiquen el contenido de la etiqueta HTML que los representa en la vista es muy poderosa. El siguiente ejemplo muestra un TagHelper que modifica su contenido pasándolo a mayúsculas:

[snippet id=”201″]

Gracias a que el valor de [ContentBehavior] es Modify, el valor inicial de la propiedad Output del parámetro output contiene el contenido de la etiqueta HTML asociada al TagHelper. Lo interesante es que los TagHelpers se pueden anidar, ejecutándose primero los hijos y posteriormente los padres. Así, si en la vista tenemos:

[snippet id=”202″]

El código HTML generado y enviado al cliente será:

[snippet id=”203″]

Se puede observar como el TagHelper interno (Demo) ha sido generado primero y todo su contenido (incluyendo por cierto el nombre de la etiqueta span generada por dicho TagHelper) ha sido pasado a mayúsculas por el TagHelper Upper.

Otra posibilidad de los TagHelpers es no solo añadir nuestras propias etiquetas HTML a las vistas Razor, si no reemplazar etiquetas HTML tradicionales. Así podríamos tener un TagHelper asociado a la etiqueta HTML <input>, de forma que cuando se encontrase un <input> en una vista Razor su contenido fuese renderizado a través del TagHelper. De este modo podríamos sustituir los @Html.TextBoxFor.

Un ejemplo quizá un poco más realista sería el siguiente:

[snippet id=”204″]

Este TagHelper está asociado a la etiqueta HTML <a>. En este caso se ha optado por el uso del atributo [TagName] en lugar la convención de que el nombre de la clase determina el nombre de la etiqueta HTML asociada como en los ejemplos anteriores. Por lo demás el código es bastante sencillo, pero voy a destacar tres aspectos:

  1. El TagHelper declara que su ContentBehavior es None. Es decir no puede modificar el contenido de la etiqueta HTML asociada, pero sí que puede añadir atributos a dicha etiqueta (de hecho podría reemplazarla por otra si quisese estableciendo el valor de la propiedad TagName del parámetro output). En este caso el TagHelper se limita a añadir el atributo href, dejando el resto tal y como está.
  2. El uso del atributo [Activate] en las propiedades ViewContext y UrlHelper para que el valor de dichas propiedades sea inyectada por el sistema de inyección de dependencias que incorpora ASP.NET 5 de serie.
  3. El código del método ParseData es necesario porque el método Action del IUrlHelper tiene problemas para entender el resultado tal cual de JSonConvert.DeserializeObject, pero funciona correctamente cuando se le pasa un IDictionary<string, object> (funcionaría también con cualquier clase que implementase IDictionary<string, object> tal como ExpandoObject).

Este TagHelper lo podrías utilizar como sustituto del @Html.ActionLink ya que viene a tener la misma funcionalidad (generar URLs en base a una acción, un controlador y valores de ruta) pero a cambio ofrece un soporte en diseño mucho mejor (cualquier herramienta de previsualización de HTML entienden la etiqueta <a>).

Su uso en vistas Razor sería como una etiqueta <a> normal pero con los atributos controller, action y data:

[snippet id=”205″]

Por cierto, observa como los valores de ruta se pasan como una cadena en formato JSON y eso es así solo porque la propiedad Data la hemos declarado como string y luego usamos JSonConvert para tratar la entrada. Pero si quieres existe otra opción que es declarar directamente la propiedad como object. Entonces en la vista debes crear el objeto anónimo usando new y sintaxis C# de notación de objetos. Así, si la propiedad Data, en lugar de ser declarada como string la hubiésemos declarado como object en el TagHelper en la vista deberíamos usar:

[snippet id=”206″]

¿En qué se diferencian los TagHelpers de los Web ControlsParece que son lo mismo: tenemos una etiqueta (ya sea <demo> o <asp:Calendar>) que es tratada por el servidor (ya sea Razor o webforms) para generar código HTML que es el que se envía al cliente. Pero la diferencia fundamental es que los Web Controls ofrecen la ilusión de tener estado y exponen un conjunto de propiedades y de eventos en el lado del servidor. Este enfoque es la base de webforms y es radicalmente distinto al de MVC y al de los TagHelpers: estos “no existen” en el servidor (controlador) tan solo son, como su nombre indica, una ayuda para encapsular la generación de HTML sin ofrecer ningún mecanismo de persistencia de estado ni ciclo de vida en servidor. Así realmente se parecen mucho más a los helpers Razor tradicionales que a los web controls.

Bueno y con esto terminamos esta entrada dedicada a los TagHelpers. Espero que os haya resultado interesante 😉

2 comentarios en “ASP.NET 5 Introducción a los TagHelpers”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *