Sobre el lanzamiento de ASP.NET MVC 3 beta, NuPack y WebMatrix beta 2

Como sabréis, hace unos días pudimos asistir y participar en el alboroto digital que provoca la presentación de nuevos productos y versiones por parte de Microsoft. Una tarde realmente divertida, en la que el aluvión de mensajes, análisis y comentarios vía Twitter hacía difícil concentrarse en algo ajeno a este festival.

Y todo se debía a la publicación, prácticamente de forma simultánea, de la primera beta de ASP.NET MVC 3, Nupack, y WebMatrix beta 2, que demuestra que la familia de tecnologías para Web sigue madurando y creciendo, y que existe alguna conspiración cuyo objetivo final es volvernos locos a todos 😉

Vamos a comentar por encima qué nos traen estos lanzamientos.

ASP.NET MVC 3 Beta

ASP.NET MVCContra todo pronóstico, ASP.NET MVC 3 Beta rompe el patrón seguido en las versiones anteriores, en las que el ciclo de desarrollo prácticamente rondaba el año, y en cuya secuencia habían sido incluidas hasta el momento varias previews y algunas betas antes de llegar al producto final.

En esta ocasión, la primera preview de ASP.NET MVC 3 apareció unos tres meses después de la versión 2, y la beta dos meses más tarde.

Como tiene que haber gente para todo, hay quien se queja de que esto puede significar que a Microsoft ha dejado de interesarle el feedback de los desarrolladores. En mi opinión, esto no tiene sentido, y no hay intención maquiavélica por detrás: simplemente, esta entrega no es tan compleja y amplia como la primera versión, donde se partía de cero, o su incremental hacia la versión 2. Aunque algunas de las novedades que se vislumbran son bastante interesantes, no se han introducido características realmente rompedoras o que requieran un gran tiempo de pruebas o una gran retroalimentación, y además, parte de ellas son compartidas con otros productos como WebMatrix.

Otro tema distinto, y creo que criticable, es la velocidad con la que se están sucediendo las distintas versiones del producto. Hace unos días comentaba vía Twitter que es difícil construir sobre una infraestructura que está en continuo movimiento; a veces las cosas hay que dejarlas reposar un poco para que asienten y calen los conceptos, se cree comunidad, software de referencia o documentación, que, desde mi punto de vista, son algunos de los handicaps actuales frente a la adopción del framework ASP.NET MVC por parte de los desarrolladores.

Pero bueno, en cualquier caso, para los que ya estamos enganchados a ASP.NET MVC, la llegada de una nueva revisión es siempre una buena noticia. La beta que podemos descargar hoy (ojo, sólo para .NET 4) ya incluye la mayoría de características que tendremos disponibles cuando aparezca la versión final, para la que, como se deja entrever en el roadmap del producto, podría faltar únicamente una release candidate, en la que aparentemente no serán incluidas muchas más novedades.

A modo de resumen, las características que a día de hoy parece que traerá el futuro ASP.NET MVC 3 son, principalmente:

  • Mayor flexibilidad para el uso de motores de vistas alternativos a WebForms.
  • El nuevo motor de vistas Razor, compartido por la tecnología WebPages. Eso sí, aún no está disponible intellisense en el editor de Visual Studio para estas vistas.
  • Un soporte para inyección de dependencias muy mejorado respecto a las versiones anteriores.
  • Registro de filtros globales durante la inicialización de la aplicación.
  • Nuevos tipos de resultados (ActionResults) de uso común.
  • Mejoras en el sistema de validación, soportando nuevos atributos,  generación de scripts en cliente de forma más sencilla, y nuevas fórmulas para la inclusión de validación no intrusiva.
  • Soporte para funcionalidades Ajax no intrusivas.
  • Inclusión de capacidad de binding sobre JSON.
  • Nuevas vías para enviar información del controlador a las vistas, de forma dinámica.
  • Helpers para la realización de tareas de uso frecuente, como la generación de grids, charts, o manipulación de imágenes.
  • Control individual sobre la validación de la petición (vaya, ahora que había encontrado un truquillo para conseguirlo).
  • Incluye el gestor de paquetes Nupack, que comentaré algo más abajo.

No sé si me dejaré algo por detrás, pero de todas formas ya iré desgranando estos temas en futuros posts.
Para conocer las novedades de la beta 2 respecto a la Preview, te recomiendo que leas el post de Eduard Tomás, escrito con el producto aún humeante, recién salido del horno 😉

¿Nupack? ¿Eso qué es?

Nupack Otra de las grandes estrellas de la tarde del miércoles fue Nupack, un gestor de paquetes open source que está llamado a ser una herramienta imprescindible para los desarrolladores. La versión presentada es bastante preliminar, CTP1, pero funciona muy bien y es útil para empezar a conocerla.

Por hacernos una idea rápida sobre el nuevo producto, podríamos considerar que Nupack es a librerías y componentes lo que Web Platform Installer a aplicaciones y plataformas. Se trata de un gestor de paquetes integrado en Visual Studio que permite obtener componentes open source (y, lo que es más interesante, las dependencias de éstos), e incluirlos en nuestros proyectos de forma muy sencilla.

Y con “incluirlos” no me refiero a descargarlos y dejarlos en un directorio para que nosotros hagamos el resto; Nupack lo descarga y extrae sobre una carpeta de uso interno, añade las referencias necesarias a nuestro proyecto, y, cuando es necesario, añade archivos y modifica educadamente los ficheros de configuración del proyecto.

Los paquetes disponibles en Nupack se obtienen de una serie de repositorios de software open source, por supuesto configurables. En estos momentos hay ya más de 70 paquetes entre los que se encuentran de uso más frecuente, aunque supongo que el número continuará aumentando.

Para añadir un componente a un proyecto basta con abrir el menú contextual sobre las referencias y seleccionar la opción “Add Package Reference”, que nos llevará a un cuadro de diálogo como el mostrado a continuación, que nos permite buscar e incluir los paquetes de forma más visual:

Añadiendo un paquete con Nupack
También podemos utilizar Nupack desde una línea de comandos incluida en Visual Studio (Package Manager Console). La siguiente captura muestra lo simple que resulta añadir un componente como T4MVC a un proyecto utilizando la consola:

Añadiendo T4MVC a un proyecto
Esta última fórmula, además de resultar muy cómoda, está diseñada para ser extensible, por lo que es posible descargar e instalar paquetes que amplíen sus funciones, como MvcScaffold, que añade a la consola órdenes para generar código de vistas más rápidamente que utilizando su equivalente GUI, y de forma similar a como se hace en otras plataformas como Ruby.

Nupack se incluye “de serie” con ASP.NET MVC 3 Beta, por lo que si has instalado éste último, ya podrás disfrutar de esta nueva herramienta. Si no, puedes descargarlo desde la página del proyecto Nupack en Codeplex.

Si quieres utilizar Nupack desde la consola de comandos, debes tener instalado previamente PowerShell 2.0. En caso de necesitarlo, puedes bajarlo, por ejemplo, con Web Platform Installer.

Un último detalle: Nupack, aunque se haya presentado así, unido a otros lanzamientos de la pila de tecnologías Web de Microsoft, no está ligado a éstas. Se trata de una herramienta independiente, de la que podremos sacar partido en todo tipo de proyecto.

En resumen, desde mi punto de vista se trata de una herramienta excelente, presente en otros ámbitos y tecnologías, y que ya venía haciendo falta a Visual Studio y los desarrolladores .NET. Si quieres saber más sobre el tema, no te pierdas el gran post de Scott Hanselman explicando su uso.

WebMatrix Beta 2

WebMatrix Hace unos meses, al aparecer la primera beta ya describí mis primeras impresiones sobre WebMatrix, por lo que no voy a extenderme demasiado ahora.

Para los despistadillos, recordar que WebMatrix es un conjunto de herramientas y plataformas destinadas a crear aplicaciones basadas en el paradigma de “orientación a página” (como ASP clásico o PHP, entre otros), e incluye:

  • IIS 7 Express, una edición reducida del servicio de publicación web.
  • SQL Server Compact, un motor de datos capaz de ejecutarse en el proceso de la aplicación que lo utiliza, por tanto sin necesidad de instalar software alguno en servidor.
  • Un entorno de desarrollo, compuesto por:
    • un editor de texto plano bastante simplillo para crear y modificar las páginas,
    • un diseñador de bases de datos,
    • herramienta de generación de informes SEO del sitio,
  • Integración con un extenso repositorio de software libre (.NET y PHP, principalmente), del que es posible descargar aplicaciones para personalizarlas o construir sobre ellas de forma rápida.
  • Tecnología WebPages, un nuevo modelo de desarrollo sobre ASP.NET que permite la creación de sitios web utilizando el nuevo motor Razor.

Esta segunda Beta trae algunas novedades interesantes relativas a WebPages y Razor.

Se ha incluido un gestor de paquetes basado en web, que permitirá añadir nuevos helpers y componentes al sistema. Para ello, basta con acceder desde el navegador a la carpeta “_Admin” en el raíz del sitio web; la primera vez nos solicitará la introducción de una contraseña que deberemos utilizar en adelante. Una superado este trámite, podremos instalar los paquetes desde la misma página:

Gestor de paquetes en Webmatrix
También han sido añadidos nuevos helpers, renombrado algunos métodos y clases existentes, y se ha introducido validación de peticiones a nivel de campo, al igual que a MVC 3. En definitiva, cambios que podríamos considerar de menor calado.

Puedes leer más en el documento Readme de WebMatrix beta 2.

En fin, que…

… de nuevo nos encontramos ante una oleada de tecnologías y herramientas, algunas bastante destacables, a las que debemos ir haciendo hueco en nuestra mochila y a las que conviene ir echando el ojo de vez en cuando para poder seguirles el ritmo.

Sin duda, diversión asegurada. 🙂

Publicado en: Variable not found.

Referenciar scripts, estilos y otros recursos desde vistas MVC

ASP.NET MVC Una cuestión que consultan frecuentemente los alumnos del curso de MVC que tutorizo en CampusMVP, y que veo en los foros oficiales del framework trata sobre el uso correcto de rutas hacia recursos utilizados por las páginas, como scripts, estilos o imágenes.

Unas referencias erróneas hacia las páginas de estilo o imágenes pueden hacer que un sitio web, o parte de éste, deje de visualizarse correctamente; en el tema de scripts es más grave pues en el peor de los casos el sistema puede dejar de funcionar o presentar un comportamiento anómalo, sobre todo si se hace uso intensivo de bibliotecas como jQuery o MS Ajax.

Para mayor desgracia, muchas veces la aparición de estos síntomas es tardía. Todo parece funcionar correctamente en desarrollo, con el servidor integrado de Visual Studio, y falla estrepitosamente al publicarlo en el IIS de producción, lo cual puede provocar un cierto nerviosismo y la aparición de frases como «¡en mi máquina funciona!» ;-).

¿Y por qué es tan habitual encontrar problemas en esto, a priori tan sencillo? En mi opinión, por las prisas y la comodidad, sin duda malas compañías para los desarrolladores. Y conste que no seré yo quien tire la primera piedra…

Sin duda es realmente cómodo arrastrar un recurso (script, estilo…) desde el explorador de proyectos y dejarlo caer sobre una vista; Visual Studio es lo suficientemente inteligente como para generar la etiqueta apropiada para referenciarlo.

Por ejemplo, editando el archivo /Views/Home/Index.aspx, podemos arrastrar directamente el archivo /Content/Site.css y el entorno generará un tag <link> completo:

Arrastrar recurso sobre una vistaSin embargo, si nos fijamos bien, la ruta que está creando hacia el recurso no es del todo correcta.

En tiempo de diseño el entorno no sabe qué URL será utilizada para acceder a la página, por lo que incluye en el código es la ubicación relativa del recurso respecto a la ubicación de la vista actual en el sistema de archivos.

Por ello, en el ejemplo anterior, editando el archivo /Views/Home/Index.aspx ha generado la ruta relativa hacia la carpeta Content, que incluye dos saltos hacia arriba en la estructura de carpetas para llegar al raíz, más el acceso al archivo desde éste.

Esto puede ser válido si estamos editando páginas en un entorno en el que las peticiones son mapeadas directamente contra el sistema de archivos, pero no en MVC, donde las rutas son tan fácilmente manipulables.

De la misma forma, tampoco sería válido en escenarios WebForms donde la ubicación de la página no coincida con la de la petición actual, como las páginas maestras o controles de usuario, o si utilizamos las nuevas capacidades de routing de .NET 4.

Volviendo de nuevo al ejemplo anterior, aunque la vista esté implementada en el archivo  /Views/Home/Index.aspx, el acceso a la misma podría realizarse, utilizando la ruta por defecto, mediante la URL http://servidor/, lo que implica que la referencia relativa de la hoja de estilos estaría saliéndose del ámbito de la aplicación, es decir, se estaría intentando acceder dos niveles por arriba de la carpeta de publicación del proyecto.

En el servidor web integrado en Visual Studio nuestra aplicación funcionará correctamente al ignorar los intentos de subir más allá del raíz de la aplicación, lo que retrasa la detección del problema. Al publicar en IIS, bastante menos permisivo, nos encontraremos con que nuestra aplicación ha dejado de funcionar.

Afortunadamente hay soluciones para todos los gustos. De hecho, más que soluciones para cuando aparezca el problema, deberíamos tomarlas como buenas prácticas a la hora de referenciar cualquier tipo de elemento desde el principio del desarrollo.

Veamos algunas de ellas.

Solución 0: Cambiar las rutas a mano

La “solución” más artesana es, sin duda, introducir manualmente las rutas en todas las referencias hacia recursos externos de la vista. De hecho, en realidad nos puede ayudar a solucionar el problema descrito anteriormente, pero es bastante poco flexible, y no muy recomendable.

Así, el ejemplo anterior podríamos editar el código generado por Visual Studio y sustituirlo por el siguiente:

<link href="/Content/Site.css" rel="stylesheet" type="text/css" />

Como observaréis, hemos eliminado la porción “../../” de la ruta, por lo que la hoja de estilos ya estaría referenciada correctamente, ¿no?

Pues depende. Si nuestra aplicación se publica en el raíz de un dominio o subdominio, todo será correcto; en cambio, si queremos desplegarla en un directorio ya la hemos vuelto a liar, puesto que la referencia asume que la carpeta “Content” se encuentra en el raíz.

Por experiencia, suele ser bastante habitual que durante el desarrollo de una aplicación se cuelguen versiones de demostración en directorios privados, y una vez terminada se pasen al raíz de su dominio. Ante este escenario, si las rutas las hemos indicado de forma absoluta, en vez de una solución, hacer este cambio es sólo introducir una nueva fuente de problemas.

Solución 1: Usar el helper Url.Content()

El helper Url.Content() nos permite obtener la URL del recurso cuya ubicación física estamos pasándole como parámetro. Dado que el resultado se calcula en tiempo de ejecución, el framework ya dispone de información suficiente para generar la dirección correcta.

La forma de usarlo, muy sencilla. Observad el uso del gusanillo “~” para hacer referencia al directorio raíz de la aplicación:

<link href="<%= Url.Content("~/Content/Site.css")%>" rel="stylesheet" type="text/css" />
<script src="<%= Url.Content("~/Scripts/jquery-1.4.1.js")%>" 
        type="text/javascript" /></script>

Este enfoque sí aporta una solución definitiva al problema, aunque a la hora de codificarlo sea algo tedioso.

Solución 2: usar T4MVC

Otra alternativa, sin duda interesante, para generar la ruta correcta es utilizar la magnífica herramienta T4MVC, de la que ya hemos hablado por aquí algunas veces. Muy resumidamente, T4MVC es una plantilla de generación de código automático capaz de analizar el contenido de nuestro proyecto y generar “constantes” que nos permitan eliminar los literales de texto en las aplicaciones MVC.

Así, por ejemplo, tras su inclusión en nuestro proyecto, la propiedad pública  Links.Content.Site_css contendrá la ruta correcta hacia el archivo ~/Content/Site.css, calculada en tiempo de ejecución, por lo que podríamos dejar el código anterior en:

<link href="<%= Links.Content.Site_css %>" rel="stylesheet" type="text/css" />
<script src="<%= Links.Scripts.jquery_1_4_1_js %>" 
        type="text/javascript" /></script>

Observad que hemos eliminado la llamada a Url.Content(), puesto que ya las propiedades utilizadas están calculando la ruta correcta.

Una ventaja adicional de T4MVC es que podría detectarse en tiempo de compilación la ausencia de un archivo. Si después de introducir el código anterior eliminamos los archivos referenciados, al compilar la vista se produciría un error. Además, durante la codificación podemos disfrutar de intellisense para descubrir los archivos y evitar errores.

Solución 3: Crear nuestros propios helpers

Ya sabemos que el framework ASP.NET MVC está, desde sus inicios, preparado para ser fácilmente extendido, y los helpers Html de las vistas no iban a ser la excepción.

Si por cualquier extraño e incomprensible motivo no quieres o puedes utilizar T4MVC, siempre podrías construirte tus propios helpers. En el siguiente ejemplo, vemos cómo con un par de llamadas podríamos simplificar la generación de las etiquetas de referencia a scripts y estilos en una página:

<head>
<title>Mi sitio web</title>
<%= Html.IncludeStyles("site.css", "ui.jqgrid.css", "redmond/jquery-ui-1.8.2.custom.css")%>
<%= Html.IncludeScripts("jquery-1.4.1.min.js", "jquery-ui-1.8.2.custom.min.js", 
                        "grid.locale-sp.js", "jquery.jqGrid.min.js")%>
</head>

Como se puede intuir, estos helpers generarán las etiquetas <style> y <script> correspondientes para todos los archivos que se les suministre como parámetros. El código, el siguiente:

 
public static class HtmlIncludeHelpers
{
    public static MvcHtmlString IncludeScripts(this HtmlHelper html, 
                                               params string[] scriptNames)
    {
        return generateContent(
                    html,
                    @"<script type=""text/javascript"" src=""{0}""></script>",
                    "~/Scripts/",
                    scriptNames
        );
    }
 
    public static MvcHtmlString IncludeStyles(this HtmlHelper html, 
                                              params string[] fileNames)
    {
        return generateContent(
                    html,
                    @"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" />",
                    "~/Content/",
                    fileNames
        );
    }
 
    private static MvcHtmlString generateContent(HtmlHelper helper, string tag, 
                                                 string root, IEnumerable<string> files)
    {
        StringBuilder sb = new StringBuilder();
        if (files != null)
        {
            string path = UrlHelper.GenerateContentUrl(root, helper.ViewContext.HttpContext);
            foreach (var file in files)
            {
                sb.AppendFormat(tag, Path.Combine(path, file));
            }
        }
        return MvcHtmlString.Create(sb.ToString());
        
    }
}

(He dejado este código en Skydrive).

En definitiva, existen mil y un patrones que podemos utilizar para evitar problemas en la generación de rutas hacia los recursos de una página. Espero que lo planteado en este post puedan seros de ayuda a la hora de diseñar vuestra propia solución.

Publicado en: Variable not found.