Razor Helpers

Para aquellos que venimos trabajando desde el inicio con ASP.NET MVC recordaran que con la versión de MVC 3 aparecía Razor, el view engine que nos permitía armar vistas mas simples escribiendo menos caracteres 🙂

Hoy vamos a hablar de una característica de Razor que muchas veces se nos pasa por alto, pero que les puede resultar muy útil. Se trata de la sintaxis @helper que nos permite escribir métodos auxiliares re-utilizables en las vistas.

Trabajemos en un simple ejemplo para apreciar la utilidad de esta sintaxis. Supongamos que tenemos una lista que muestra información sobre personas y en una de las columnas es necesario mostrar su dirección postal. Para el caso en que no existiera esta información hay que mostrar la frase “No se cuenta con la dirección postal“.

Como ya se imaginan, esto requiere escribir una simple porción de lógica en la vista que muestre el texto que corresponda dada una condición determinada. Para esto vamos a crear un método auxiliar con la sintaxis @helper que vamos a llamar MostrarDireccionPostal:

Definiendo un Razor Helper

Definiendo un Razor Helper

Sencillo, no?… Seguramente se estarán preguntando cómo podemos hacer para reutilizar esté método en otras vistas de mi aplicación sin necesidad de re-escribir el @helper en cada una de estas vistas. Para esto simplemente debemos mover nuestro método a un archivo con extensión .cshtml o .vbhtml dentro del directorio “/App_Code” (en mi caso lo voy a llamar SebysHelpers.cshtml):

SebysHelpers Template

SebysHelpers Template

Tengan en cuenta que el template SebysHelpers.cshtml se compila bajo la clase SebysHelpers la cual me va a proveer del método estático MostrarDireccionPostal (dentro del template podemos poner cuantos métodos queramos). Hecho esto finalmente resta modificar la vista para invocar el método correspondiente:

Invocando al método dentro del template.

Invocando al método del template.

Como podemos ver el uso de la sintaxis @helper nos permite encapsular lógica del renderizado de las vistas en métodos auxiliares que podemos compartir entre deferentes vistas de una manera muy sencilla y generando código mas legible y mantenible.

Espero que les sea de mucha utilidad.

Abrazos!

Visualizando la versión de la aplicación en proyectos ASP.NET MVC

Un recurso muy útil con lo que contamos los programadores .NET es la clase AssemblyInfo que se encuentra ubicada generalmente en el directorio-archivo “Properties\AssemblyInfo.cs“. Entre otros usos, nos permite definir y obtener – de manera centralizada – el número de versión de una aplicación.

MSDN la define de la siguiente manera:

Proporciona las propiedades para obtener información sobre la aplicación, como el número de versión, la descripción, los ensamblados cargados, etc.

Ahora bien, la forma más simple de definir la versión actual de la aplicación es actualizando el siguiente atributo de AssemblyInfo:

Atributo AssemblyVersion

Atributo AssemblyVersion

Para mostrar este dato actualizado en nuestro sitio, solo debemos agregar a la vista la siguiente línea (un buen lugar es el pie de página):

Agregando la versión a la vista.

Agregando la versión a la vista.

Tengan en cuenta que la versión que queremos visualizar en este caso corresponde el ensamblado de la aplicación web, que en este ejemplo se encontraría bajo el namespace Web.WebApiAplication.

Resultado:

Visualizando la versión de la app en el pie.

Visualizando la versión de la app en el pie.

Espero que les sea de utilidad!

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.

ASP.NET MVC – Gestionando la memoria Cache

Hace un tiempo que estoy leyendo acerca de HTML y algunos de los temas que me llamo la atención fueron sobre la directiva HEAD. Esta directiva corresponde al encabezado de un documento HTML y contiene información que nos ayuda a interpretar y mantener el contenido de su cuerpo – BODY.

<html>
<head>
<title>Title of the document</title>
</head>
<body>
The content of the document……
</body>
</html>

Una de las directivas que componen el encabezado es META. Esta directiva suele tener dos usos: como contenedor de meta-información sobre el documento (generalmente utilizada para indexar dichos documentos con los navegadores), o como contenedor de información adicional relacionada con el protocolo HTTP . Si deseamos utilizar la directiva META para el primer caso, debemos hacer uso del atributo NAME y para el segundo caso el atributo HTTP-EQUIV. Un ejemplo de ambos uso es el siguiente:

<head>
<meta name=”description” content=”Free Web tutorials” />
<meta name=”keywords” content=”HTML,CSS,XML,JavaScript” />
<meta name=”author” content=”Hege Refsnes” />
<meta http-equiv=”content-type” content=”text/html;charset=UTF-8″ />
</head>

La etiqueta HTTP-EQUIV, nos permite tener control sobre los navegadores, y suelen ser utilizadas para: recargas automáticas de página, controlar la cache del navegador, especificar la fecha de espiración del documento o el lenguaje “nativo” del mismo entre otras opciones.

En esta oportunidad, nos vamos a enfocar en la administración de la cache del documento, la cual esta espeficiada por el valor “cache-control“:

<meta http-equiv=”cache-control” content=”no-cache” />

Nota: para los nostálgicos, en Netscape la misma se representaba de la siguiente manera:

<meta http-equiv=”pragma” content=”no-cache/cache” />

Los valores posibles del encabezado cache-control son:

  • public: las caches de los clientes y las cachés compartidas (de servidores proxy) pueden almacenar la respuesta.
  • private: la respuesta sólo se almacena en la memoria caché del cliente y no en memorias caché compartidas (servidor proxy).
  • no-cache: no cache.
  • no-store: se realiza la cache del contenido pero no es archivada.

Veremos más adelante que .NET provee un enumerado de dichos valores.

Otros atributos que podemos especificar en este encabezado son los siguientes:

  • max-age: representa el tiempo de caducidad, especificado en segundos, y se cuenta a partir del momento en que se realiza la petición del recurso, por lo que ofrece mayor flexibilidad.
  • s-maxage: similar a max-age, pero sólo se aplica a cachés proxy.
  • must-revalidate: comunica a las cachés que deben seguir estrictamente todas nuestras reglas sobre la caducidad de los recursos. El protocolo HTTP da a las cachés cierta libertad a este respecto, la cual se puede restringir con esta directriz.
  • proxy-revalidate: similar a must-revalidate, pero sólo se aplica a cachés proxy.

Ahora bien, teniendo en cuenta todo esto, podríamos crear un filtro de acción en ASP.NET MVC para establecer que nuestras páginas sean almacenen en la memoria cache. Para esto vamos a crear la clase CacheAttribut que deberá heredar de la clase ActionFilterAttribute.

Una de las propiedades de dicha clase será la duración de la cache (representada en segundos) y la segunda el valor del encabezado HTTP Cache-Control representado por enumerado HttpCacheability:

Valores posibles del encabezado HTTP Cache-Control

Valores posibles del enumerado HttpCacheability

Para poder indicarle al navegador que queremos almacenar en la chace la página que estamos sirviendo, necesitamos interceptar la ejecución de la misma y agregar en el encabezado directivas META con el atributo http-equiv correspondiente al manejo de la cache. Para esto vamos a sobre-escribir el método OnActionExecuted en el nuevo filtro de acción:

Como vemos, el parametro que recibe este método es del tipo ActionExecutedContext y representa el contexto en el cual se esta ejecutando una acción. Una de las propiedades es del tipo HttpCachePolicyBase la cual nos permitirá establecer las políticas de caché de la página web.

Veamos una definición mas completa que no brinda MSDN sobre el namespace System.Web.HttpCachePolicyBase:

Actúa como clase base para las clases que contienen métodos para establoecer los encabezados HTTP específicos de la memoria caché y para controlar la memoria caché de resultados de las páginas ASP.NET.

Ok, ahora ya tenemos listo nuestro ActionFilter, vamos a ponerlo a prueba. 🙂

Lo primero será ejecutar nuestra aplicación sin el uso de cache, para eso definimos una vista llamada Index de la forma habitual, y veamos la respuesta del servidor:

Respuesta del servidor

Respuesta del servidor

Sin especificar nada en el proyecto, ASP.NET MVC retorna páginas con el tipo de cache Private sin ningún otro tipo de especificación.

Ahora vamos a agregarle el atributo Cache, especificando que será del tipo Public con una duración de 60 segundos:

Ejecutemos y veamos la respuesta:

Respuesta del servidor

Respuesta del servidor

Como veran, la memoria cache esta especificada como Public, con una duración (max-age) de 60 segundos. También tenemos con información del encabezado la fecha y hora en que expira la misma.

Para terminar, quiero decirles que ASP.NET MVC ya nos provee de un filtro de acción que nos permite establecer cuestiones propias de la cache: el action filter OutputCache. Veamos un ejemplo rápido de su uso, en este caso para especificar que no queremos utilizar ningun tipo de cache en la vista:


La respuesta del servidor es la siguiente:

Respuesta del servidor

Respuesta del servidor

Vean que la fecha de espiración de la cache es la misma fecha en la que es devuelto el documento, por lo que al servir nuevamente la página la misma se obtendrá directamente del servidor y no de la cache del servidor proxy o del cliente. Utilizando esta librería podemos realizar configuraciones del manejo de la cache de manera global al sitio, o crear distintos perfiles de cache especificandolos en el archivo web.config.

Recomiendo que lean el siguiente tutorial del sitio oficial de ASP.NET MVC acerca de este tema.

Quienes quieran descargar el proyecto pueden hacerlo desde acá: MyMvcApplication – ManejoMemoriaCache.rar.

Espero que les sea de utilidad!

ASP.NET MVC : Entendiendo ResponseRedirect

Quienes desarrollamos en algún momento en ASP.NET Webform no necesitábamos tener conocimientos web de bajo nivel ya que los mismos eran abstraídos por el mismo framework. Esto se debía a que ASP.NET, en ese entonces, había sido pensado para atraer a los desarrolladores de aplicaciones de escritorio que se resistían pasar al desarrollo de aplicaciones web. Por lo tanto, la estrategia de MS fue seguir con esa misma filosofía.

En el momento en que uno hace el pase a ASP.NET MVC – cosa que recomiendo a todo desarrollador web de .NET 🙂 – tiene la necesidad de conocer más en profundidad estas cuestiones (HTTP, HTML, CSS…), ya que es parte de la naturaleza del framework y facilita enormemente el desarrollo sobre el mismo.

Como mencione anteriormente, una de las cuestiones web son los protocolos y  hace un tiempo atrás participé de la excelente VAN que presento Leonardo Micheloni sobre HTTP (llamada “HTTP y las ruedas de la web“) donde uno de los tema que toco fueron los distintos códigos de estado que provee este protocolo.

Para quienes no conozcan demasiado de este tema cuando uno hace una petición por medio de una URL se inicia una transacción desde el cliente que termina con una respuesta del servidor que generalmente viene compuesta por el recurso solicitado (sea un HTML, XML…). Uno de los datos que viajan en el encabezado de la respuesta es el código de estado (de los cuales los más conocidos son 200 OK o 404 NOT FOUND).

Estos códigos de estado se encuentran agrupados según su función y uno de esos grupos corresponden a las Redirecciones : 3xx.

Todo esto me hizo pensar en como funcionaba realmente el método RedirectToAction que nos provee la clase Controller de ASP.NET MVC.  Y mis sospecha – no demasiadas brillantes – eran ciertas, la solicitud a una vista que utiliza RedirectToAction retorna HTTP Code Status 302.

Antes de continuar, veamos un poco más en profundidad, de que se trata el código 302 viendo una definición de Wikipedia:

Este es el código de redirección más popular, pero también un ejemplo de las prácticas de la industria contradiciendo el estándar. La especificación HTTP/1.0 (RFC 1945) requería que el cliente realizara una redirección temporal (la frase descriptiva original fue “Moved Temporarily”), pero los navegadores populares lo implementaron como 303 See Other. Por tanto, HTTP/1.1 añadió códigos de estado 303 y 307 para eliminar la ambigüedad entre ambos comportamientos. Sin embargo, la mayoría de aplicaciones web y bibliotecas de desarrollo aún utilizan el código de respuesta 302 como si fuera el 303.

Luego de esta larga introducción, vayamos al grano y definamos dos vistas, la primera la llamaremos Index y la segunda Final. Lo que hará la primer vista será simplemente redireccionar a la segunda:

1: public class HomeController : Controller
2: {
3:     public ActionResult Index()
4:     {
5:         return RedirectToAction("Final");
6:     }
7:
8:     public ActionResult Final()
9:     {
10:         return View();
11:     }
12: }

Ejecutemos y analicemos la respuesta del servidor:

Respuesta HTTP

Respuesta HTTP

Vemos que la petición GET a la URL “http://localhost…/Index&#8221; retorna el código 302 Found, y seguido se hace una nueva petición a “http://localhost…/Final&#8221; que finalmente es devuelta exitosamente (retornando el código 2oo OK).

Para saber donde tiene que hacer la redirección, uno de los datos que viajan en el encabezado de la respuesta es Location el cual contiene dicha información:

Encabezado de la respuesta HTTP

Encabezado de la respuesta HTTP

Es importante que entendamos como funcionan estas cuestiones, que si bien son simples, uno muchas veces las desconoce pensando que todo es resuelto “magicamente” por el framework.

Espero que les haya sido de utilidad.

Evitando JavaScript Injection en ASP.NET MVC

Hace unos días revisando un informe de sobre seguridad web, un ítem me llamo la atención porque es una de esas cosas que a uno se olvida de tenerlas en cuenta al momento de desarrollar un sitio. El mismo hablaba sobre los ataques de inyección de JavaScript.

Este tipo de ataque se denomina Cross-site scripting o de manera abreviada XSS:

XSS, del inglés Cross-site scripting es un tipo de inseguridad informática o agujero de seguridad basado en la explotación de vulnerabilidades del sistema de validación de HTML incrustado.

La idea de este post es ver de que forma podemos prevenir este tipo de ataques en aplicaciones ASP.NET MVC partiendo desde dos ópticas diferentes.

Antes que nada vamos a ver un poco mas en profundidad de que se trata JavaScript Injection y como se llevan a cabo este tipo de ataques. Para darnos una mejor idea supongamos que desde nuestro sitio web tenemos una caja de texto en la cual un usuario carga contenido y luego el mismo se visualiza en la página. Esta situación podría estar dejando abierta la posibilidad de un ataque de inyección de Javascript. Cómo es posible esto?… vamos a verlo con un simple ejemplo.

Lo primero sera crear una aplicación web tipo Twitter pero muy simplificada, en la cual vamos a permitir este tipo de ataques. Vamos a crear un controlador al cual vamos a llamar TweetController y a definir la siguiente entidad que formará parte del modelo de nuestra app y que se llamaremos Tweet:

1: public class Tweet
2: {
3:     public int TweetID { get ; set ; }
4:
5:    public string Usuario { get ; set ; }
6:
7:     public string Mensaje { get ; set ; }
8: }

Al momento de codificar la vista, la visualización de los items estará armada de la forma estandar:

1: <div class="tweetSection">
2:  <% foreach (var item in Model) {  %> 
3:     <span class="tweetUser">  <%= item.Usuario %></span>
4:    <br />
5:      <%= item.Mensaje  %> 
6:     <br />
7:     <br />
8:  <%   }  %>
9: </div>

Básicamente nuestra app esta conformada por un formulario donde se ingresa un nombre de usuario y un mensaje, el cual al momento de hacer el submit se grabara en una DB (para esto utilizaremos la librería EF) y luego se visualizara en la misma pantalla:

Interfaz de la aplicación

Interfaz de la aplicación

De la forma en que “dibujamos” el formulario, hemos dejado desprotegido nuestro sitio a los ataques de este tipo. Imaginemos que el usuario escribe un simple script de Javascript en nuestra caja de texto, por ejemplo, la ejecución de un mensaje de alerta informándonos que hemos sido atacados:

Cargando un script JS en el formulario

Cargando un script JS en el formulario

Una vez que “tweeteamos” nuestro contenido y volvemos a cargar la vista (que incluye la visualización del contenido de cada uno de los tweets) se estará ejecutando nuestro script:

Ataque de Javascript Injection

Ataque de Javascript Injection

Uno puede pensar que este tipo de ataques son inofensivos, sin embargo un hacker podría utilizar la inyección de JavaScript para realizar un ataque Cross-Site Scripting (XSS) robando información confidencial del usuario y enviando la misma a otro sitio web (dos ejemplos clásicos serían robar información de las cookies del navegador del usuario o información que se carga en un formulario que previamente a sido victima de Javascript Injection).

Cómo podemos evitar este ataque? Tenemos dos alternativas, la primera es utilizar el helper HTML.Encode el cual se encargara de renderizar el contenido de forma tal que no se ejecuten scripts que alguien pudo ingresar:

1: <div class="tweetSection">
2:  <% foreach (var item in Model) {  %> 
3:     <span class="tweetUser">  <%= item.Usuario %></span>
4:     <br />
5:      <%= Html.Encode(item.Mensaje)  %> 
6:     <br />
7:     <br />
8:  <%   }  %>

Ejecutamos y vemos que ya no se ejecuta nuestro script, ya que todo contenido reconocido como HTML a sido codificado de forma tal que se pueda visualizar como texto:

Utilizando el Helper Html.Encode

Utilizando el Helper Html.Encode

La segunda alternativa es codificar el contenido antes de grabarlo en la base de datos. Para esto podemos hacer uso del método Server.HtmlEncode que nos provee nuestro controlador:

1:             if (ModelState.IsValid)
2:             {
3:                 tweet.Mensaje = Server.HtmlEncode(tweet.Mensaje);
4:                 datos.Tweets.Add(tweet);
5:                 datos.SaveChanges();
6:             }

Utilizando este esquema ya no sería necesario utilizar el helper Html.Encode para visualizar el contenido (aunque no esta demás dejarlo). La desventaja de este enfoque es que los datos que se graban en la base de datos están codificados, lo cual no es del todo prolijo sobre todo si esta información se necesita visualizar en otro tipo de plataformas que no sean web. Observemos a continuación como se guardan los datos sin codificar (registro 2) y codificandolos (registro 3):

Registros de la base de datos

Registros de la base de datos

Para finalizar quería comentarles que utilizando el ViewEngine Razor los datos son “encodeados” automaticamente, sin necesidad de utilizar el helper Html.Encode y previniendonos de este tipo de ataques de entrada.  🙂

Quienes quieren el proyecto del ejemplo pueden descargarlo desde aquí: Projecto MvcJavascriptInjection

MvcScaffolding

En esta oportunidad quiero mostrarles la librería MvcScaffolding que me pareció por demás interesante y que trabaja en conjunto con Entity Framework y ASP.NET MVC 3. La finalidad principal de esta librería es facilitarnos tareas comunes y repetitivas de desarrollo que nos quitan tiempo y productividad.

Pero antes de comenzar vamos a ver que significa el termino Scaffold en nuestro ambito:

El termino Scaffolding es utilizado en muchas tecnologías de software para representar una forma rápida de generar un esquema básico de software que se puede editar y personalizar.

Con esta librería a partir de un modelo definido y escribiendo solo un par de comandos vamos a poder generar: la base de datos, los controladores con sus métodos de acción y sus respectivas vistas. Qué beneficios nos trae esto? que nos vamos a evitar tener que hacer esas tediosas acciones repetitivas como por ejemplo los formularios de carga y edición para las entidades más simples de nuestro proyecto.

Para comenzar lo primero que vamos hacer es crear un nuevo proyecto ASP.NET MVC 3 e instalar los paquetes Eyntity Framework y MvcScaffolding.

Para instalar ambas librerías podemos utilizar la consola que nos provee Nuget (en este post solo voy a mostrar como instalar el paquete MvcScaffolding, aunque la instalación de EF es similar). Para eso vamos a la opción “Tools\Library Package Manager\Package Manager Console” la cual nos abrirá la consola en una pestaña. Ahí escribimos el siguiente comando “Install-Package MvcScaffolding” y presionamos “Enter“:

Instalando MvcScafollding

Instalando MvcScafollding

Una vez que tenemos las librerías que vamos a utilizar instaladas vamos a definir el mismo modelo que en anteriores post y que estará compuesto por las entidades Agenda y Evento:

1:     public class Agenda
2:     {
3:         public int AgendaId { get ; set ; }
4:         public string Propietario { get ; set ; }
5:         public DateTime FechaCreacion { get ; set ; }
6:
7:         public virtual ICollection <Evento> Eventos { get ; set ; }
8:     }
1:     public class Evento
2:     {
3:         public int EventoId { get ; set ; }
4:         public int AgendaID { get ; set ; }
5:         public DateTime Fecha { get ; set ; }
6:         public string Comentario { get ; set ; }
7:
8:         public virtual Agenda Agenda { get ; set ; }
9:     }

Si seguiríamos con el procedimiento normal para armar nuestra aplicación, el siguiente paso seria escribir el controlador y las acciones que necesitamos para trabajar con nuestra Agenda y por último crear cada una de las vistas, cierto?… la idea de MvcScafollding es automatizar dicho proceso y simplemente escribiendo un par de lineas de comando generar nuestras interfaces CRUD (es decir, el listado de registros y los formularios de alta, baja, detalle y modificación de la entidad).

Vamos a abrir nuevamente la consola desde el menú “Tools\Library Package Manager\Package Manager Console” y escribimos el siguiente comando: “Scafolld Controller Agenda” (podemos observar que la última palabra del comando corresponde al nombre de la clase Agenda) y presionamos ENTER. Haremos lo mismo con la otra clase de nuestro modelo que es Evento.

Generando las interfaces UI y DB a partir del modelo

Generando las interfaces UI y DB a partir del modelo.

Podemos observar que entre otras cosas nos genero el controlador, las vistas y hasta el contexto de la base de datos automáticamente 🙂 :

Archivos generados

Archivos generados

Ejecutemos nuestra aplicación y accedamos a la vista de la Agenda (o a la de Eventos) para observar que ambos formularios están totalmente funcionales y persisten en la base de datos 🙂

Formulario de alta de una agenda

Formulario de alta de una agenda

Sin embargo, si vamos a la vista de eventos, el combo para seleccionar la agenda a la cual pertenece no se ve correctamente, esto debido a que en el modelo no se especifico que propiedad de la agenda queremos visualizar:

Error al visualizar el combo de Agendas

Error al visualizar el combo de Agendas

Para corregir esto simplemente agregamos el atributo DisplayColumn (provisto por la librería DataAnottations) a la clase Agenda pasandole como parámetro el atributo que deseamos que se visualice, en nuestro caso el Propietario de la misma:

1: [DisplayColumn ("Propietario")]
2: public class Agenda
3: {
4:     public int AgendaId { get ; set ; }
5:     public string Propietario { get ; set ; }
6:     public DateTime FechaCreacion { get ; set ; }
7:
8:     public virtual ICollection<Evento> Eventos { get ; set ; }
9: }

Volvemos a ejecutar y tenemos listo el formulario:

Combo de agendas mostrando el atributo que elegimos

Combo de agendas mostrando el atributo que elegimos

Una de las cosas que me llamo la atención de esta librería es forma en que arma los listados (o vistas index) ya que agregó una columna que nos permite saber el número de eventos que tiene cada agenda:

Listado de agendas

Listado de agendas

Con lo que respecta a la base de datos, la librería MvcScafollding esta integrada con Entity Framework y por default trabajan con base de datos SqlExpress. Un punto importante a saber es que el nombre con que se genera la base de datos coincide con el nombre completo del DbContext, en nuestro ejemplo el nombre de la DB es el siguiente MvcScaffolding.Models.MvcScaffoldingContext.

Otra de las cosas que me llamo la atención, es que no encontraba la cadena de conexión a la base de datos por ningun lado. Luego de leer un poco, me encontré con que, si no se especifica la cadena de conexión en el archivo web.config, EF lo que hará es generar “dinamicamente” la conexión a la base de datos utilizando el nombre del DbContext que estará corriendo sobre la instalacia local del SqlExpress (en mi caso .\SQLExpress). Recordemos que EF trabaja con el esquema de convenciones sobre el de configuraciones.

Cadena de conexión

Cadena de conexión

Pero bien podríamos modificarlo para que trabaje con SqlCE simplemente modificando la cadena de conexión dentro del archivo web.config como explicamos en este post.

Antes de finalizar el post, les voy a nombre algunas de las caracteristicas que ofrece MvcScaffolding:

  • Soporte para proyectos en C # como en VB.
  • Soporte para los ViewEngines Razor y ASPX.
  • Se pueden personalizar el código generado editando los templates T4.
  • Personalizar la lógica utilizada para generar las salidas modificando la lógica del PowerShell y de los templates T4.

Espero que les haya servido y que sigan investigando sobre esta librería que tiene muchísimo más para ofrecerles.