ASP.NET MVC – Template Helpers

Generalmente se nos presentan situaciones en donde nuestro modelo posee varias entidades que comparten una misma propiedad. Supongamos que estamos trabajando un proyecto web ASP.NET MVC, y debemos armar el formulario para la administración de dichas entidades (operaciones CRUD). Nada mejor para estos casos que generar una vista parcial por cada una de estas propiedades “compartidas”, que entre otros beneficios nos permitiría reutilizar código, cierto?… si embargo, esto puede generar ciertos dolores de cabeza que a priori no teníamos en mente.

Para empezar con el ejemplo, veamos las entidades que conformaran el modelo, la primera de ellas representa un cliente – ClienteModel -, y la segunda una dirección – DireccionModel – que en nuestro caso será el atributo compartido:

Clases del Modelo

Clases del Modelo

Como podemos ver, el modelo DireccionModel se podría utilizar en muchas otras entidades, como por ejemplo, modelos para representar  un usuario, un proveedor, una empresa, etc.

Basándonos en el modelo previamente definido, la forma mas simple para generar el formulario de carga o edición sería crear la siguiente vista de tipado fuerte (strongly-typed view):

Formulario de cliente

Formulario de cliente

El formulario obtenido sería el siguiente:

Formulario de edición

Formulario de edición

Si completamos los datos del formulario y hacemos el submit del mismo, podremos validar que el binding del modelo se hizo de correctamente:

Enviando los datos del formulario

Enviando los datos del formulario

Ahora bien, como comentamos al inicio, podríamos generar una vista parcial donde poner los datos de la dirección solamente y poder reutilizarla en otros formularios. Quedaría algo como lo siguiente:

Vista parcial con los datos de la dirección

Vista parcial con los datos de la dirección

Finalmente modificamos la vista Edit agregando la referencia a la vista parcial:

Referenciando a la vista parcial

Referenciando a la vista parcial

Ejecutamos y vemos que el formulario obtenido es el “mismo”, aunque esto solo es en el aspecto “visual“. Si analizamos el HTML resultante, veremos que los inputs generados para la carga de la calle y el número tienen el atributo name diferente al que se generaba en el primer caso. Esto sucede porque los strongly-type helpers para construir los elementos del formulario utilizan expresiones lanbdas que se basan en el modelo proporcionado.

Comparemos los elementos HTML construidos utilizando vistas parciales y sin utilizarlas:

Html generados

Html generados

Los nombres generados son diferentes, porque los modelos utilizados en el strongly-type helper son diferentes, en el caso de las vistas parciales el modelo es DireccionModel  y en el otro caso modelo es ClienteModel.

Como ya sabemos, el atributo NAME es utilizado por ASP.NET MVC para bindear los datos del formulario con el modelo que espera el método de acción del controlador. En la vista parcial no estamos respetando el nombre de la propiedad de la clase Cliente a los cuales pertenecen estos campos y por consiguiente los datos no son enviados al método de acción del controlador. 😦

Modelo obtenido utilizando vistas parciales

Modelo obtenido utilizando vistas parciales

Entonces… de que manera puedo reutilizar código, si no podemos utilizar las vistas parciales? (aclaración, no es que no podamos utilizar vistas parciales, existen otras formas de solucionar este problema, sin embargo no son el propósito de este post). Una solución es utilizar Template Helpers que, a diferencia de las vistas parciales, reciben información del contexto padre.

Para crear nuestro template helper, lo primero que debemos hacer es generar una nueva carpeta llamada “EditorTemplates” dentro de “Views/Shared” (esta ubicación nos permitirá utilizar el template desde diferentes vistas) y mover ahí la vista parcial que habiamos creado, pero que ahora llamaremos con el mismo nombre del modelo DireccionModel.cshtml:

Moviendo nuestra vista parcial

Moviendo nuestra vista parcial

Bien, ahora solo resta modificar la vista Edit que invocara por medio del strongly-type helper Html.EditorFor a las vista del modelo correspondiente:

Utlizando Template Helper

Utlizando Template Helper

Ejecutamos y veremos que los datos del formulario si son enviados al método de acción del controlador:

Enviando los datos del formulario

Enviando los datos del formulario

En este caso, el modelo que recibe el template no es DireccionModel (o sí) sino la entidad que lo contiene, por lo que el elemento del formulario se generará con el name correcto.

Existen muchisimas mas características, como por ejemplo el helper Html.Display, que tiene un comportamiento similar al helper Html.Editor solo que es utilizado para visualizar los valores de una entidad. Les recomiendo leer este excelente post de Brad Wilson para más información.