Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
Mostrando entradas con la etiqueta consultas. Mostrar todas las entradas
Mostrando entradas con la etiqueta consultas. Mostrar todas las entradas
martes, 21 de enero de 2014
Usando la KatanaA través del formulario de contacto del blog, el amigo Carlos G. L. me enviaba una pregunta a raíz del último post de la serie sobre OWIN/Katana, relativo al uso de stage markers:
(...) entonces, ¿esto quiere decir que podemos utilizar un middleware para dar soporte CORS a soluciones basadas en la primera versión de WebAPI o en MVC 4?
Respuesta corta: sí. Siempre que se cumplan los requisitos de plataforma exigidos por Katana y los middlewares que queramos usar, nada impide hacerlo sobre aplicaciones con versiones anteriores de estos frameworks.

Y vamos con la respuesta larga…
martes, 14 de febrero de 2012
ASP.NET MVCComo sabemos, los helpers como Url.Action() y Html.ActionLink() son capaces de generar URLs hacia acciones partiendo de la información disponible en la tabla de rutas y de los parámetros que les suministramos.

Por ejemplo, el siguiente código genera un enlace hacia la acción Edit del controlador Friends, suministrándole el valor 3 al parámetro de ruta id:
@Html.ActionLink("Edit friend", "Edit", "Friends", new {id = 3}, null)
Sin embargo, estos helpers no nos ayudan demasiado cuando desconocemos a priori el valor de los parámetros. De hecho, si en lugar del 3 que hemos suministrado quisiéramos enviar un valor obtenido a través de scripting tendríamos un problema, puesto que el bloque de código anterior se ejecuta en servidor y el enlace sería generado antes incluso de ejecutarse el script para obtener el valor a enviar.

Esta es una pregunta que suelo ver muy a menudo en comunidades y foros (como el de ASP.NET MVC en MSDN) y me han realizado más de una vez en el curso de ASP.NET MVC 3 que tutorizo en CampusMVP, así que vamos a ver un par de enfoques para enfrentarnos a este escenario, bastante frecuente al trabajar en sistemas web y, sobre todo, en aquellos muy basados en scripting y Ajax.
martes, 10 de enero de 2012
ASP.NET MVCHace poco escribía un post en el que mostraba cómo se podía conseguir establecer el foco inicialmente en un control de edición, algo que era posible con Webforms pero no directamente con las herramientas que ASP.NET MVC trae de fábrica.

La solución propuesta consistía en introducir en la vista código de script para desplazar el foco hasta el control indicado mediante una llamada al helper Html.SetFocusTo(), que implementábamos en el mismo post, aunque hay otras formas para conseguirlo.

miércoles, 5 de octubre de 2011
ASP.NET MVCHace unos días, el amigo Cadavid realizaba una consulta en los comentarios de la serie de posts que escribí hace unos meses sobre el helper Webgrid, sobre cómo podíamos implementar filtros personalizados sobre los datos mostrados, y dado que no es algo que se pueda explicar en un simple comentario, me comprometí a escribir un post sobre el tema, así que ahí va.

El problema fundamental es que WebGrid no incorpora ningún tipo de ayuda para realizar esta tarea tan frecuente; simplemente se encarga de mostrar los datos que le suministremos, por lo que si queremos filtrarlos debemos hacerlo de forma manual. En pura teoría bastaría con hacer llegar a Controlador los filtros a aplicar, y que éste consultara la información desde el Modelo teniendo en cuenta los criterios establecidos.

Sin embargo, algo que puede parecer relativamente simple se complica un poco si queremos, además, mantener intacta la capacidad de ordenación y paginación de datos, puesto que debemos encargarnos también del mantenimiento del estado entre peticiones. Pero vaya, no es nada que no podamos solucionar en unos minutos ;-)

martes, 10 de mayo de 2011
ASP.NET MVCHace unos días me llegaba, vía formulario de contacto del blog, una consulta cuya respuesta pienso que puede resultar interesante para alguien más, así que ahí va.

El problema con el que se encuentra el amigo F. H. es algo con lo que ya me topé hace tiempo al intentar utilizar el helper EditorFor() con propiedades anulables.

Para los que todavía no lo habéis utilizado, comentar que el helper EditorFor() de ASP.NET MVC es una ayuda imprescindible para crear de forma muy rápida potentes interfaces de introducción de datos. Por ejemplo, hace tiempo vimos cómo podíamos utilizarlo para crear un editor de propiedades de tipo fecha usando jQuery datepicker, y que quedaba la mar de bien ;-)

Plantillas de edición en ASP.NET MVCSu uso es muy sencillo. Si tenemos una propiedad del modelo, por ejemplo Edad, de tipo int, podemos desde la vista generar un editor apropiado para ella utilizando la expresión:

    @Html.EditorFor(model => model.Edad)


En tiempo de ejecución, el framework buscará en la carpeta /Views/Shared/EditorTemplates si existe una vista parcial con el nombre del tipo (int32 en este caso, que es el nombre real del tipo en la plataforma .NET), y la mostrará para que el usuario pueda editar el valor de esta propiedad.

El siguiente código podría ser una plantilla de edición válida para el ejemplo anterior, el contenido que podríamos encontrar dentro del archivo int32.cshtml:

@model int
@Html.TextBox("", 
            Model, 
            new { maxlength=8, style="width: 100px; text-align: right;"  }
)

Como se puede observar, simplemente estamos creando un cuadro de texto, con un estilo determinado y una capacidad máxima de 8 caracteres.

Pues bien, y volviendo al tema del post, el problema que comentaba este amigo de Variable not found es que cuando, en lugar de tratarse de un tipo valor puro (como int32, DateTime, double, etc.) se trata de un tipo anulable (int?, DateTime?, double?…) todo va bien mientras el contenido que queremos editar no sea un nulo, momento en que aparecerá el siguiente error:
El modelo pasado al diccionario es NULL, pero este diccionario requiere un elemento de modelo distinto de NULL de tipo ‘System.Int32’.

El modelo pasado al diccionario es NULL, pero este diccionario requiere un elemento de modelo distinto de NULL de tipo ‘System.Int32’.


Básicamente, lo que nos indica el error es que en la plantilla de edición estamos esperando un int, como hemos indicado con la directiva @model de Razor, y estamos recibiendo un valor nulo, lo cual es absolutamente incompatible.

Aunque a priori parece que el problema se podría solucionar creando en la carpeta EditorTemplates otra plantilla exclusiva para el tipo anulable int32? , rápidamente nos damos cuenta de que esto no sería una tarea sencilla. El nombre interno de los tipos anulables, como de cualquier otro tipo genérico, está bastante lejos de ser manejable e intuitivo… no, la solución es mucho más simple.

ASP.NET MVC utiliza la misma plantilla de edición para los tipos anulables y sus tipos valor correspondiente. Así, la vista int32.cshtml será utilizada tanto para editar las propiedades de tipo int como las int?. Esto hace que la solución al problema sea, simplemente, modificar ésta para que acepte el tipo correcto de datos, y gestionar los nulos de la forma que más nos interese, por ejemplo mostrando un cero como valor por defecto en el cuadro de edición, como en el siguiente código:

@model int?
@Html.TextBox("", 
            Model ?? 0, 
            new { maxlength=8, style="width: 100px; text-align: right;"  }
)

¡Y eso es todo! Espero que la duda quede resuelta, y que pueda ser de utilidad a alguien más :-)

Publicado en: Variable not found.
martes, 26 de octubre de 2010
ASP.NET MVC A raíz de la publicación del post anterior, en el que comentaba el uso de helpers locales para simplificar el código de las vistas, un amigo de Variable not found ha dejado un comentario con una pregunta que considero interesante: ¿se puede utilizar esta técnica con el motor Razor, presente en el inminente MVC 3?

Los helpers locales descritos en el post anterior son y seguirán siendo válidos en MVC 1, 2, 3, y posiblemente todos los que vengan detrás, puesto que en realidad se trataba únicamente de aprovechar una característica del motor de vistas basado en formularios web, es decir, el Webforms View Engine, el mismo utilizado en las aplicaciones ASP.NET “clásicas”.

Por tanto, si en MVC 3 seguimos utilizando el motor de vistas Webforms, podremos crear helpers locales tal y como se describía en el post anterior. Sin embargo, si utilizamos el motor de vistas Razor, los bloques <script runat="server"> serán ignorados, al igual que otras características propias de formularios web.

Razor dispone de su propia sintaxis para definir funciones locales utilizando el bloque @functions, como puede observarse en el ejemplo mostrado a continuación:

image

En el interior del bloque @functions podemos crear tantas funciones como necesitemos, por lo que podemos conseguir exactamente lo mismo que con su equivalente Webforms.

Publicado en: Variable not found.
martes, 7 de septiembre de 2010
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());
        
    }
}


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.
lunes, 3 de mayo de 2010
10 Preguntas con respuesta ASP.NET MVC En marzo de 2008 publiqué un megapost en el que se recogían respuestas a diez preguntas básicas sobre el framework ASP.NET MVC, que por aquellos entonces se encontraba todavía en una versión muy preliminar, la Preview 2.

Más de un año después, coincidiendo con el lanzamiento de la versión 1.0, actualicé el contenido y las preguntas conforme a la evolución de los desarrollos y a lo que había podido profundizar en el tema desde entonces, en el post ASP.NET MVC: Trece preguntas básicas.

Y de nuevo en 2010, continuando lo que ya parece que es una tradición, aprovecho el reciente lanzamiento de ASP.NET MVC 2 para actualizar las respuestas y añadir algunas nuevas cuestiones básicas que pienso pueden resultar de interés a desarrolladores que todavía no conocen este nuevo marco de trabajo de Microsoft.

Trataré de responder a las siguientes preguntas:
  1. Empecemos desde el principio, ¿qué es MVC?
  2. ¿Qué ventajas tiene el uso del patrón MVC?
  3. ¿Qué es ASP.NET MVC framework?
  4. Espera… pero entonces, ¿programar con ASP.NET MVC no consiste en usar Webforms, pero separando los componentes en capas?
  5. ¿Es el primer framework MVC creado para .NET?
  6. Como desarrollador de aplicaciones web con ASP.NET, ¿me afectará la llegada de este framework?
  7. Entonces, ¿no significa la aparición del framework MVC la muerte próxima de los Webforms de ASP.NET?
  8. Pero… ¿Vale la pena pasarse a ASP.NET MVC o sigo usando Webforms?
  9. Pero siempre que leo algo sobre MVC viene rodeado de un gran número de conceptos extraños como IoC o DI. ¿Es que ASP.NET MVC es sólo para gurús?
  10. ¿Puedo convertir mi proyecto ASP.NET Webforms a ASP.NET MVC?
  11. ¿Se puede utilizar Ajax con el framework MVC?
  12. ¿Se puede utilizar VB.NET con ASP.NET MVC?
  13. ¿Puedo usar LINQ desarrollando aplicaciones con ASP.NET MVC framework?
  14. ¿Qué tipo de tecnologías puedo utilizar en las vistas?
  15. ¿Es ASP.NET MVC framework software libre?
El post es un poco extenso, así que mejor que os pongáis cómodos… ;-)

1. Empecemos desde el principio, ¿qué es MVC?

Aunque de forma algo simplista, podríamos definir MVC como un patrón arquitectural que describe una forma de desarrollar aplicaciones software separando los componentes en tres grupos (o capas):
  • El Modelo que contiene una representación de los datos que maneja el sistema, su lógica de negocio, y sus mecanismos de persistencia.
  • La Vista, o interfaz de usuario, que compone la información que se envía al cliente y los mecanismos interacción con éste.
  • El Controlador, que actúa como intermediario entre el Modelo y la Vista, gestionando el flujo de información entre ellos y las transformaciones para adaptar los datos a las necesidades de cada uno.
MVC son las siglas de Modelo-Vista-Controlador, y se trata de un modelo muy maduro y que ha demostrado su validez a lo largo de los años en todo tipo de aplicaciones, y sobre multitud de lenguajes y plataformas de desarrollo. Puedes encontrar más información en:

2. ¿Qué ventajas tiene el uso del patrón MVC?

Como siempre esto de enumerar ventajas es algo subjetivo, por lo que puede que pienses que falta o sobra alguna dímelo!). En un primer asalto podríamos aportar las siguientes:
  • Clara separación de responsabilidades entre interfaz, lógica de negocio y de control, que además provoca parte de las ventajas siguientes.
  • Facilidad para la realización de pruebas unitarias de los componentes, así como de aplicar desarrollo guiado por pruebas (TDD).
  • Simplicidad en el desarrollo y mantenimiento de los sistemas.
  • Reutilización de los componentes.
  • Facilidad para desarrollar prototipos rápidos.
  • Sencillez para crear distintas representaciones de los mismos datos.
  • Los sistemas son muy eficientes, y a la postre más escalables.
Pero bueno, también se pueden citar algunos inconvenientes:
  • Tener que ceñirse a una estructura predefinida, lo que a veces puede incrementar la complejidad del proyecto. De hecho, hay problemas que son más difíciles de resolver, o al menos cuestan algo más de trabajo, respetando el patrón MVC.
  • Al principio puede cierto esfuerzo adaptarse a esta filosofía, sobre todo a desarrolladores acostumbrados a otros modelos más cercanos al escritorio, como Webforms.
  • La distribución de componentes obliga a crear y mantener un mayor número de ficheros.

3. ¿Qué es ASP.NET MVC Framework?

ASP.NET MVC 2 Web ApplicationEs un framework, un marco de trabajo cuya segunda versión acaba de ver la luz, que ha sido creado por Microsoft con objeto de ayudarnos a desarrollar aplicaciones que sigan la filosofía MVC sobre ASP.NET.

Además del conjunto de librerías (ensamblados) que proporcionan las nuevas funcionalidades a nivel de API, incluye plantillas y herramientas que se integran en Visual Studio 2008 y 2010 (tanto en sus versiones Express como en sus hermanas mayores) para facilitarnos un poco las cosas.

Visual Studio 2010 ya incorpora ASP.NET MVC 2 de serie, mientras que en la versión 2008 es necesario descargar e instalar el software (puedes hacerlo con el Web Platform Installer u obteniéndolo desde el sitio de Microsoft).

En cualquier caso, una vez montado, Visual Studio mostrará un nuevo tipo de proyecto (ASP.NET MVC 2 Web Application) que nos permitirá crear el esqueleto básico de un proyecto de este tipo.

Y ya para cuando estemos en faena, el entorno ofrece multitud de utilidades para hacer nuestro trabajo más fácil, como la herramienta de creación de vistas automáticas, el desplazamiento entre controladores y vistas, o plantillas para la definición de controladores, entre otras.

4. Espera… pero entonces, ¿programar con ASP.NET MVC no consiste en usar Webforms, pero separando los componentes en capas?

No. ASP.NET MVC es una forma de crear aplicaciones para la web basadas en ASP.NET de una forma radicalmente distinta a los formularios web, para que te hagas una idea:
  • no existe el postback,
  • no hay viewstate,
  • no hay eventos,
  • el diseñador visual deja de tener sentido,
  • como consecuencia no hay controles de servidor, al menos en la forma en que los conocemos,
  • no es necesario utilizar los archivos code-behind de las páginas .aspx,
  • las páginas no siguen complejos ciclos de vida; de hecho, el proceso de una petición es infinitamente más simple que en Webforms,
  • nosotros controlamos totalmente el código de marcado generado,
  • también tenemos control absoluto sobre las URLs de acceso a nuestra aplicación; ahora, con ASP.NET 4 también es posible con Webforms, pero en versiones anteriores (y todavía actuales como .NET 3.5) no era tarea fácil,
  • podemos sustituir componentes internos del framework para adaptarlo a nuestras preferencias,
  • basa muchos aspectos en el concepto convención sobre configuración, tan satisfactoriamente utilizado en otros entornos,
  • se integra con Ajax de forma natural, sin artificios como los UpdatePanels y similares,
  • favorece la introducción de buenas prácticas como la inversión de control o inyección de dependencias,
… y un largo etcétera. Realmente, ASP.NET MVC es una tecnología muy distinta y que requiere que los desarrolladores tengamos que acostumbrarnos a pensar de otra manera y dedicar tiempo a aprenderla para sacarle partido.

Sin embargo, el hecho de que el framework esté creado sobre ASP.NET hace que no tengamos que partir de cero: muchos de los conocimientos que ya tenemos seguirán siendo válidos y aplicables en este nuevo contexto.

5. ¿Es el primer framework MVC creado para .NET?

No, ni el único. Existen multitud de frameworks MVC para ASP.Net, como MonoRail, Maverick.Net, FubuMVC y muchos otros.

6. Como desarrollador de aplicaciones web con ASP.NET, ¿me afectará la llegada de este framework?

No necesariamente. Puedes seguir desarrollando aplicaciones como hasta ahora, con Webforms. Si así lo decides, este nuevo framework no te afectará nada; simplemente, ignóralo.
De todas formas, ya que has leído hasta aquí, permíteme un consejo: aprende a utilizar ASP.NET MVC framework. Después podrás decidir con conocimiento de causa si te conviene o no.

7. Entonces, ¿no significa la aparición del framework MVC la muerte próxima de los Webforms de ASP.NET?

Diseñador de Webforms En absoluto. Son simplemente dos filosofías diferentes para conseguir lo mismo, ¡páginas web!

La tecnología de Webforms es muy útil para asemejar el desarrollo de aplicaciones web a las de escritorio, ocultando la complejidad derivada del entorno desconectado y stateless (sin conservación de estado) del protocolo HTTP a base de complejos roundtrips, postbacks y viewstates, lo que nos permite crear de forma muy productiva formularios impresionantes y que el funcionamiento de nuestra aplicación esté guiado por eventos, como si estuviéramos programando Winforms.

Sin embargo, esta misma potencia a veces hace que las páginas sean pesadas y difícilmente mantenibles, además de dificultar enormemente la realización de pruebas automatizadas. Y por no hablar de comportamientos extraños cuando intentamos intervenir en el ciclo de vida de las páginas, por ejemplo para la carga y descarga de controles dinámicos.

ASP.NET MVC propone una forma distinta de trabajar, más cercana a la realidad del protocolo y, curiosamente, más parecida a cómo se hacía unos años atrás, cuando controlábamos cada byte que se enviaba al cliente o se recibía de éste. No existen, por tanto, conceptos como el mantenimiento del estado en el viewstate, ni el postback, ni nos valdrán los controles de servidor basados en estas características, que en la práctica son la mayoría.

Sin embargo, dado que el framework está creado sobre ASP.NET, será posible utilizar páginas maestras, codificar las vistas en un .aspx utilizando C# o VB.NET, usar los mecanismos de seguridad internos, control de caché, gestión de sesiones, localización, etc.

8. Pero… ¿vale la pena pasarse a ASP.NET MVC o sigo usando Webforms?

En mi opinión, no se trata de decidirse por una u otra tecnología, sino de conocer ambas y utilizar la más apropiada en cada momento. Hay muchos aspectos a tener en cuenta, como:
Vamos a reflexionar sobre cada uno de estos puntos, y la decisión os la dejo a vosotros. ;-)

Conocimientos y experiencia del equipo de desarrollo

image La tecnología de formularios web (Webforms) permite el desarrollo rápido de aplicaciones (RAD) a través de diseñadores visuales con los que es posible componer una página compleja y definir el comportamiento del interfaz a golpe de ratón, puesto que el framework se encarga de realizar parte del trabajo duro, como el mantenimiento del estado entre peticiones, convertir propiedades de controles en código HTML y CSS, o incluso generar scripts que realicen determinadas tareas en cliente.

De hecho, siguiendo este modelo es posible crear aplicaciones para Internet sin tener apenas idea de las particularidades inherentes al desarrollo web, lo que permite que muchos programadores procedentes del mundo del escritorio puedan ser productivos muy rápidamente, aunque sea a costa de generar páginas mucho más pesadas y con un código de marcado complejo.

No hay que olvidar que para determinado tipo de aplicaciones, los Webforms son una buena opción, tanto como lo han sido hasta ahora. Por tanto, si el equipo de desarrollo tiene ya experiencia creando aplicaciones con esta tecnología y no posee grandes conocimientos sobre programación web de más bajo nivel ni experiencia previa trabajando con el patrón MVC, deberíamos ser prudentes antes de dar el salto a ASP.NET MVC, puesto que la productividad, al menos inicialmente, va a caer.

“Un gran poder conlleva una
gran responsabilidad”

-- El tío Ben, a Peter Parker
ASP.NET MVC requiere un conocimiento más profundo del entorno web y sus tecnologías subyacentes, puesto que a la vez que ofrece un control mucho más riguroso sobre los datos que se envían y reciben desde el cliente, exige una mayor responsabilidad por parte del desarrollador, ya que deberá encargarse él mismo de mantener el estado entre peticiones, maquetar las vistas, crear las hojas de estilo apropiadas, e incluso los scripts.

Esto, sin embargo, no difiere mucho de la forma de trabajar unos años atrás, y es posible que en el equipo de trabajo haya desarrolladores experimentados que se sientan incluso más cómodos trabajando a este nivel que utilizando abstracciones como las provistas por ASP.NET Webforms.

Necesidad de utilizar controles o sistemas preexistentes

Otro aspecto a valorar antes de dar el salto a ASP.NET MVC es que existe una altísima probabilidad de que no podamos utilizar porciones de código o componentes visuales que hayamos desarrollado previamente, lo cual redundará en los tiempos de desarrollo y productividad del equipo de trabajo.

No nos valdrán los controles de servidor, ni las plantillas de proyectos, ni los generadores de código, y en muchos casos ni siquiera la herencia de editor (que por muy antipatrón que sea seguro que acostumbramos a utilizar).

Sin embargo, y aunque en volumen no es aún comparable a Webforms, cada día existen más componentes para ASP.NET MVC de compañías dedicadas a la creación de herramientas de programación, y generados desde la propia comunidad de desarrolladores, que nos ayudan a ser más productivos.

También hay que tener en cuenta el encaje tan sencillo del framework MVC con soluciones basadas en cliente, como jQuery y su interminable colección de plugins, en los que podemos encontrar elementos de interfaz para prácticamente cualquier necesidad.

Madurez del framework

Aunque en sus principios la adopción de ASP.NET MVC framework podía suponer ciertos riesgos debidos a su escasa madurez, hoy en día ya no es así.

Gracias a la disponibilidad del código fuente y su relativa simplicidad interna, los errores que pudieran detectarse en él podrían ser rápidamente subsanados.

La madurez también se hace patente en la cantidad y calidad de información disponible. ASP.NET MVC, aunque cuenta con una comunidad de desarrolladores bastante entusiasta, son una minoría comparándola con su veterana competencia, y sobre todo en el mundo de habla hispana.

Lo mismo ocurre con el número ingente de componentes y controles reutilizables disponibles para Webforms. Dado que no son compatibles con el framework MVC, se parte de una situación de clara desventaja frente a éstos, aunque como comentaba anteriormente, esto está ya cambiando y seguro que con el tiempo seguirá a mejor.

Consideraciones sobre el futuro de la tecnología

Si lo que te preocupa es el futuro de los Webforms, has de saber que Microsoft va a seguir dándoles soporte y mejorándolos, como no podía ser de otra forma. Por tanto, de momento no es necesario que bases tu decisión en esto.

Eso sí, hay quien opina que ASP.NET MVC será el estándar de creación de sistemas web en unos años, por lo que en cualquier caso se trata de una tecnología que no habría que perder de vista…

Beneficios de ASP.NET MVC

Las ventajas de la arquitectura MVC, descritas anteriormente, y las bondades del diseño del framework son un buen aliciente para comenzar a trabajar con ASP.NET MVC.

De hecho, deberíamos tener muy en cuenta en qué aspectos nuestros desarrollos van a beneficiarse del uso de esta tecnología y valorar si estas ventajas compensan los inconvenientes que su adopción va a suponer:
  • la separación de aspectos impuesta por el patrón MVC obligará a tener un código más limpio y estructurado, independizando totalmente la interfaz de la lógica de navegación y, por supuesto, de la de negocio.
  • de la misma forma, esta división facilita el trabajo en equipo, pues permite el avance en paralelo en las distintas capas.
  • si entre nuestras prioridades está el asegurar el correcto funcionamiento de nuestros componentes a través de pruebas unitarias, o hemos optado por utilizar una metodología de desarrollo guiado por pruebas (TDD), ASP.NET MVC nos vendrá de perlas. La separación de aspectos citada anteriormente facilita la creación de pruebas específicas para los componentes de cada capa de forma independiente, así como el uso de técnicas avanzadas (mocking, inyección de dependencias…) para que éstas sean lo más completas posible.
  • las friendly URLS, o direcciones amigables, es un beneficio directo del uso del framework de Microsoft. Estrictamente hablando no es mérito de la plataforma MVC, sino del juego de clases presentes en el espacio de nombres System.Web.Routing, incluidas en .NET framework 3.5, pero en cualquier caso si optamos por esta tecnología la tendremos “de serie”, con las ventajas que ello conlleva (SEO, REST, claridad en direcciones…).
  • al final, el software será mucho más mantenible; el hecho de que los componentes estén separados y bien estructurados simplificará las tareas de mantenimiento.
  • el conjunto de convenciones en cuanto a la estructura de proyectos y de nombrado y disposición de elementos facilitará el desarrollo una vez sean asimiladas.

El tipo de sistema

A la hora de plantearse un cambio de este tipo es imprescindible tener en cuenta el tipo de proyecto en el que vamos a trabajar.

No es lo mismo desarrollar un sitio web colaborativo destinado a un gran número de usuarios, como Facebook o Digg, donde el control fino sobre la entrada y salida es crucial para asegurar aspectos como la escalabilidad, cumplimiento de estándares, o accesibilidad, que crear una aplicación de gestión que utilizarán un grupo relativamente reducido de usuarios desde una intranet corporativa.

En ambos casos se trata de crear sistemas web, pero los objetivos, requisitos y restricciones a considerar son muy diferentes.

Para el primer caso, ASP.NET MVC es una magnífica opción. La simplicidad de la arquitectura MVC hace que el ciclo de vida de las páginas de este framework sea mucho más sencillo que el de los Webforms, y la ausencia de automatismos y persistencia de estado aligera en gran medida el peso y complejidad de las páginas, lo cual redundará muy positivamente en el rendimiento del sistema.

Si además el proyecto requiere o resulta beneficiado por el uso de direcciones URL amigables (por razones de SEO, para presentar un interfaz claro de tipo REST, o cualquier otro motivo), más aún, aunque su diferencia respecto a Webforms se ha reducido ligeramente con la aparición de ASP.NET 4.

Por último, la facilidad de introducción de funcionalidades Ajax hacen de ASP.NET MVC una opción muy apropiada para estos sistemas con estilo “2.0”. Un ejemplo de aplicación real de este tipo es la famosa comunidad StackOverflow.

En cambio, el segundo caso, cuando se trata de crear pesadas aplicaciones de gestión con interfaces de usuario complejos y en las que no es especialmente relevante la calidad del código HTML enviado al cliente, ni el peso de éstas al ser entornos cerrados y controlados, ASP.NET Webforms sigue siendo una opción razonable.

Las facilidades para el desarrollo rápido de aplicaciones (RAD) son mayores utilizando formularios web, aunque sea a cambio de sacrificar aspectos como la separación de código e interfaz, o la facilidad para realización de pruebas unitarias.

9. Pero siempre que leo algo sobre MVC viene rodeado de un gran número de conceptos extraños como IoC o DI. ¿Es que ASP.NET MVC es sólo para gurús?

No, ni mucho menos. De hecho, el funcionamiento de ASP.NET MVC es en muchos aspectos bastante más sencillo que la tecnología Webforms a la que estamos habituados.

Esos términos que tan frecuentemente encontramos en posts y artículos son técnicas y patrones que podemos utilizar para mejorar la calidad de nuestras aplicaciones o extender el framework, y estrictamente hablando no tienen nada que ver con ASP.NET MVC.

Por ejemplo, la Inyección de Dependencias (DI, Dependency Injection) es una técnica que permite realizar aplicaciones cuyos componentes se encuentran muy desacoplados entre sí, lo que flexibilizar el diseño y, por ejemplo, facilita la realización de pruebas unitarias. Se trata de un patrón muy fácilmente implementable y que nos puede aportar muchos beneficios.

La inversión de control (IoC, Inversion of Control), relacionada con el concepto anterior, permite modificar en determinadas circunstancias el flujo de ejecución, cediendo la responsabilidad de realizar tareas específicas a componentes especializados externos a nuestra aplicación. El caso más típico es el uso de software IoC (llamados contenedores) para delegar a ellos la instanciación de clases, lo que permite modificar la implementación concreta de la clase de forma externa, siempre que se cumpla un contrato (normalmente, un interfaz).

También es habitual encontrar referencias a técnicas para facilitar las pruebas unitarias, como la construcción de mocks, stubs, o fakes, que conceptualmente no son más que objetos falsos cuyo comportamiento y datos preconfiguramos explícitamente para poder probar de forma más sencilla nuestros métodos.

Como puedes comprobar, se trata de tecnologías ajenas a ASP.NET MVC, pero dado que las ventajas del patrón y el buen diseño del framework favorecen la utilización de buenas prácticas como el testeo unitario, o la inyección de dependencias, conocerlas nos vendrá de perlas.

Y en cualquier caso, son conceptos son muy sencillos y fácilmente asimilables, pues responden a necesidades con las que seguro que todos hemos encontrado, aunque en su momento no conociéramos su nombre.

10. ¿Puedo convertir mi proyecto ASP.NET Webforms a ASP.NET MVC?

Sí, pero tardarás un buen rato ;-)

Al menos que conozca, no existe ninguna herramienta ni siquiera capaz de intentar realizar tal proeza.

Hay que tener en cuenta que aunque en ambos casos se trate de aplicaciones web sobre ASP.NET, el cambio de una a otra tecnología no es una mera traducción como podría ser convertir una aplicación VB.NET a C#; se trata de un nuevo marco de trabajo que afecta sobre todo a la presentación y control de flujo del sistema.

Si tienes unas buenas clases de lógica de negocio, bien aisladas de la tecnología Webforms (como debería ser, por otra parte), probablemente sean los únicos componentes que puedas reutilizar de forma directa y sin grandes cambios.

El resto, es decir, todo lo relativo a la interacción con el usuario y la lógica de control y navegación, habría que convertirlo de forma manual, y por tanto, probablemente habría que pensarse bien si vale la pena hacerlo. Por esta razón es más habitual plantear MVC como plataforma para aplicaciones de nuevo desarrollo.

11. ¿Se puede utilizar Ajax con el framework MVC?

Absolutamente. De hecho, ASP.NET MVC se lleva de fábula con librerías de scripting como las incluidas en el framework ASP.NET 3.5 SP1, 4.0, o, lo que es mejor, con la inigualable jQuery.

La limpieza de la filosofía MVC hace posible que sea realmente sencillo realizar desde cliente llamadas a los controladores mediante scripting con objeto de obtener datos, actualizar porciones de contenido de la página con el marcado de la vista correspondiente, o, en definitiva, interactuar con el servidor.

En este mismo blog puedes encontrar multitud de ejemplos de integración de jQuery y ASP.NET MVC, que aunque implementados con las previews del framework (¡a ver si un día tengo un rato y los voy actualizando!), pueden ayudarte a entender cómo hacerlo.

Otro aspecto interesante respecto a jQuery es que esta librería entró a formar parte de la plataforma de desarrollo de Microsoft hace tiempo, lo que en la práctica aporta varias ventajas:
  • jQuery y algunos de sus plugins vienen incluidos de serie en las plantillas de proyectos ASP.NET MVC, facilitando su uso desde nuestras aplicaciones;
  • asimismo, se encuentran también disponibles en las CDN de Microsoft para agilizar su distribución
  • se ha realizado un esfuerzo importante por mejorar la integración con Visual Studio de esta librería, facilitando archivos que hacen posible el disfrute de intellisense mientras la utilizamos,
  • asegura más que nunca la apuesta a jQuery como framework de implementación en cliente, al contar con el respaldo del gigante MS.
Ahora bien, dado que el framework MVC no permite el uso de controles de servidor runat="server" (al menos como veníamos haciéndolo, pues han dejado de existir aspectos tan fundamentales para ellos como el viewstate o los postbacks), vas a tener que despedirte de soluciones Ajax para Webforms como el célebre UpdatePanel o los controles del ASP.NET Ajax Control Toolkit. Pero créeme, no las echarás de menos ;-)

12. ¿Se puede utilizar VB.NET con ASP.NET MVC?

Por supuesto. Aunque la mayoría de código que se encuentra por la red utiliza C#, probablemente porque es el lenguaje en el que ha sido desarrollado y sobre el que se están exponiendo más ejemplos desde las previews más tempranas del producto, cualquier lenguaje .NET podría ser utilizado sin problema para desarrollar aplicaciones sobre este framework.

A nivel de entorno de desarrollo, Visual Basic ofrece el mismo nivel de ayudas y plantillas que C#, pero desconozco si esto es así en otros lenguajes.

13. ¿Qué tipo de tecnologías puedo usar para implementar el Modelo?

Curiosamente, una de las cosas sobre el Modelo que más llamó la atención al aparecer el framework MVC fue precisamente la ausencia de directrices o indicaciones sobre cómo debía implementarse éste. De hecho, la carpeta /Models, utilizada por convención para almacenar los componentes de esta capa, venía vacía en la versión 1.0 del producto.

La explicación, sin embargo, era bien sencilla: ASP.NET MVC es completamente independiente de del Modelo, es el desarrollador el que elige cómo implementarlo siembre que se respeten los límites impuestos por el patrón MVC.

Teniendo en cuenta las responsabilidades del Modelo, habitualmente encontraremos en esta capa:
  • entidades de negocio,
  • clases de lógica empresarial, que implementan los procesos y reglas de negocio,
  • mecanismos de acceso a datos, por ejemplo usando directamente las clases de ADO.NET, o mejor aún, un ORM que nos aísle de la persistencia, como Linq2Sql, Entity framework o el veterano NHibernate.

14. ¿Qué tipo de tecnologías puedo utilizar en las vistas?

El objetivo de las vistas es componer el interfaz de usuario y los mecanismos de interacción con el usuario. Lo habitual, por tanto, será utilizar algún lenguaje de marcado, como XHTML ó HTML, CSS y Javascript, aderezado con bloques de código de servidor que se ejecutará en el momento de renderizar la página.

También puedes utilizar la tecnología Ajax para enviar u obtener información desde el servidor, siempre mediante llamadas a acciones definidas en el controlador, que te permitirán crear interfaces más dinámicos y actuales.

Pero sobre todo, nada de utilizar controles de servidor (Label, Button, Dropdowns…). Estos deberán ser sustituidos por sus elementos (X)HTML equivalentes, lo que implica que perderemos los automatismos provistos por Webforms para el mantenimiento del estado de los controles.

<for each="var name in names">
  <test if="name == 'Jose'">
    <p>Yo mismo</p>
    <else/>
    <p>Amigo: ${name}  
  </test>
</for>
Otra posibilidad interesante que aprovecha y demuestra la flexibilidad de la arquitectura de ASP.NET MVC framework, es la utilización de motores de vistas distintos al estándar.

Existen multitud de motores ligeros (NHaml, Spark, Brail, NVelocity…), cada uno con su propio lenguaje de marcas y convenciones, que permiten la definición de vistas a partir de plantillas como la que se muestra en el lateral (ejemplo de Spark).

15. ¿Es ASP.NET MVC framework software libre?

Pues sí, ASP.NET MVC Framework es software libre. A primeros de abril de 2009 se comenzó a distribuir oficialmente el código fuente de ASP.NET MVC con licencia MS-PL (Microsoft Public License), un modelo de licencia aprobado por la OSI (Open Source Initiative) que permite el uso del software en aplicaciones comerciales y no comerciales.

Esto, entre otras ventajas, supuso la rápida adopción del framework MVC en las plataformas .NET alternativas, como el célebre proyecto Mono, con el que es totalmente compatible. Incluso MonoDevelop dispone de herramientas y ayudas específicas para aplicaciones ASP.NET MVC.

El código fuente de ASP.NET MVC se publica en Codeplex, prácticamente de forma simultánea a las distintas revisiones que son lanzadas.

__________________________________________________

¡Hasta aquí hemos llegado! Si has sido capaz de leer el post entero, enhorabuena ;-) Espero que te haya sido de utilidad, y te sirva como motivación para introducirte en esta tecnología.

Y por supuesto, si hay algo que no te queda claro o piensas que falta alguna cuestión básica de este tipo, no dudes en añadir un comentario, o contactar conmigo vía formulario.

Publicado en: http://www.variablenotfound.com/
Facebookeado en: http://facebook.com/variablenotfound
Twitteado en: http://twitter.com/jmaguilar
domingo, 7 de marzo de 2010
ASP.NET MVC Esta es una respuesta rápida a una cuestión de Fred C., que me llega vía formulario de contacto en Variable not found, sobre un problemilla que también sufrí en algunas ocasiones, y he pensado que posiblemente pueda interesarle a alguien más, así que ahí va.

El escenario es el siguiente: tenemos en una vista un código para generar un enlace hacia una acción, como el mostrado a continuación:

<%= Html.ActionLink("Acceso externo",    // Texto del enlace
                    "Editar",            // Acción
                    "Productos",         // Controlador
                    new { id=Model.Id }) // Parámetros
%>

ActionLink() generanAl mostrarse la vista, ya en tiempo de ejecución, nos encontramos con que no se ha generado el enlace que pretendíamos, sino uno como el mostrado en la captura de pantalla adjunta, hacia la dirección/Home/Editar?Length=9.

En primer lugar, utilizando la ruta por defecto, vemos nos está llevando hacia el controlador “Home”, ¿pero no le habíamos dicho que era “Productos”?

Y en segundo lugar, ¿dónde está nuestro parámetro id? ¿De dónde sale ese parámetro Length con el valor 9?

La respuesta a este problema es bien sencilla aunque al principio puede provocarnos algún dolor de cabeza: estamos utilizando una sobrecarga incorrecta del método ActionLink().

Si observamos las distintas sobrecargas de este método, podremos comprobar que sólo una de ellas tiene una signatura compatible con la llamada que estamos utilizando:

public static string ActionLink(
    this HtmlHelper htmlHelper,
    string linkText,
    string actionName,
    object routeValues,
    object htmlAttributes
)
Así, cuando en el código anterior estábamos pasando al método el nombre del controlador, en realidad lo que hacíamos era indicarle los parámetros de la llamada. Eso explica el parámetro Length=9 en la URL: dado que le enviamos un string de 9 caracteres, simplemente se trata de una serialización de sus propiedades.

Y, por tanto, los parámetros de la llamada que estábamos especificando, lo hacíamos como parte de los atributos HTML. De hecho, si analizamos el código fuente de la página generada, encontramos que el parámetro “id” ha sido introducido como un atributo HTML del enlace:

<a href="/Home/Editar?Length=9" id="8">Editar este producto</a>

La forma de solucionarlo es bien fácil, sólo hay que utilizar la sobrecarga apropiada, como:

<%= Html.ActionLink("Editar este producto", 
            "Editar",                     // Acción
            new {                         // Parámetros
            controller="Productos", 
            id=Model.Id 
}
) %> 
 
// O Bien:
 
<%= Html.ActionLink(
             "Editar este producto", 
             "Editar",               // Acción  
             "Productos",            // Controlador
             new { id=Model.Id },    // Parámetros
             null                    // Atributos HTML
) %> 

En fin, que se trata de un pequeño despiste a la hora de codificar, propiciado a veces por la gran cantidad de sobrecargas y la información, algo confusa, ofrecida por Intellisense que nos puede hacer perder unos minutos muy valiosos.

¡Gracias, Fred, por participar en Variable not found!
Por cierto, ¡estoy en Twitter!