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!
domingo, 12 de septiembre de 2010
Y tras el paréntesis vacacional, también volvemos con los posts que resumen los enlaces difundidos desde Variable not found en Facebook y Twitter durante los últimos días.

Van dedicados al amigo Sebastián H., que según me comenta por correo, le resultan muy interesantes. :-)
Y no olvides que puedes seguir esta información en vivo y en directo desde Variable not found en Facebook, o a través de Twitter.

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.
domingo, 5 de septiembre de 2010
Por mucho que nos las merezcamos y queramos alargarlas hasta el infinito, las vacaciones también tienen que terminar. Gracias a esto mantenemos la ilusión y ganas de que lleguen las próximas, ¿no? ;-)

Así que, tras unos días de reentrada suave, aquí estamos de nuevo. Con las pilas a tope y listos para comenzar una nueva temporada que seguro será magnífica… a pesar de la que está cayendo ahí fuera.

Queda, pues, inaugurada la temporada 2010-2011 de Variable Not Found, donde espero contar, como siempre, con vuestra compañía y apoyo.

¡Nos vemos por aquí!

Publicado en: Variable not found.
lunes, 26 de julio de 2010
Hace unos días he iniciado las vacaciones, y con ellas el descenso de actividad tradicional en Variable not found (bueno, y en esta ocasión también podréis notarlo en Facebook y Twitter), por lo que dejaré de daros la lata durante algún tiempecito.

El PortilComo en otras ocasiones, los destinos elegidos para descansar son El Portil, una tranquila playa en la provincia de Huelva, y Sanlúcar de Barrameda, una maravillosa localidad costera de Cádiz.

Aunque seguiré atento al mail y no voy a dejar de trabajar durante este tiempo (ya os comentaré el nuevo proyecto que me traigo entre manos), sí que relajaré el tiempo de dedicación con objeto de recargar las pilas para el próximo año que, según se está planteando, será de lo más emocionante.

Dejo cerrado los comentarios anónimos para evitar que los spammers conviertan esto en un festival de enlaces a sitios inapropiados. Ah, no, no hace falta… ya los había cerrado hace algunas semanas precisamente por eso, así que nada. ;-P

Nos vemos a la vuelta.

Felices vacaciones, amigos ;-)

Publicado en: http://www.variablenotfound.com/.
miércoles, 14 de julio de 2010
Variable not found es un blog cuyos lectores son en su mayoría esporádicos y proceden de motores de búsqueda: aterrizan, miran lo que les interesa, se van, y la mayoría de ellos no vuelven. Obviamente estos usuarios son bienvenidos y alegra saber que cada día los posts de VNF llegan a más gente.

Sin embargo, el dato que siempre he valorado más para hacerme una idea de la aceptación de un blog es el número de suscriptores a los feeds, puesto que implican una respuesta activa del lector hacia los contenidos. Se trata de personas que, voluntariamente, deciden en un momento u otro añadirte como fuente a su lector favorito, mostrando así de forma explícita su interés por tu trabajo.

Y aunque sé que Feedburner no es demasiado preciso, que este dato suele oscilar bastante y que probablemente en unas horas ya no será así, me váis a permitir que lo celebre un poco...

¡Hemos superado los mil suscriptores a los feeds en Variable not found! :-))

1029 suscriptores en Variable not found

¡Mil gracias a todos!

Publicado en: Variable not found
martes, 13 de julio de 2010
Elegir elementos para la caja de herramientasHacía tiempo que Visual Studio 2008 me estaba dando problemas al intentar añadir controles a la caja de herramientas. Concretamente, tras pulsar el botón derecho del ratón sobre esta zona y seleccionar la opción “Elegir elementos”, el entorno se cerraba bruscamente sin dar ningún tipo de explicación.

Aunque hasta ahora he podido convivir pacíficamente con este problema (básicamente, no añadiendo controles al Toolbox ;-)), hace unos días decidí dedicar un rato a solucionarlo.

En primer lugar, dado que el casque no mostraba ningún mensaje de error previo, he acudido al visor de eventos de Windows, encontrándome con el siguiente mensaje:
.NET Runtime version 2.0.50727.3603 - Error grave de motor de ejecución (7A036050) (80131506)
Instalando el hotfixAfortunadamente, es una pista suficiente para dar con la solución. Googleando un poco los códigos de error 7A036050 y 80131506, he dado con el hotfix KB963676, que es posible descargar desde Microsoft Connect.

Una vez instalado el software apropiado para nuestra plataforma (x86, x64…) y reiniciado el equipo, todo ha vuelto a la normalidad.

Y es que a veces bastan unos minutos para eliminar esos pequeños y molestos inconvenientes que nos hacen menos productivos. Lo que es la procrastinación ;-)

Publicado en: Variable not found
Twitteado en: twitter.com/jmaguilar
Facebookeado en: facebook.com/variablenotfound