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!
martes, 26 de enero de 2010
“Error al conectarse al administrador de deshacer del archivo de código fuente c:\blahblah\archivo.designer.cs” es un mensaje con el que Visual Studio (tanto la versión 2005 como 2008) me ha abofeteado en numerosas ocasiones cuando estoy desarrollando sitios web ASP.NET.

Y la verdad, es uno de esos casos en los que no sabes qué hacer: recompilas, limpias la solución, abres y cierras el IDE… pero nada, cuando le da por ahí, no hay forma de hacerlo entrar en razón:

Error al conectarse al administrador de deshacer del archivo de código fuente

Como ya habría corregido el problema en el momento de escribir este post y no pude reproducirlo para capturar la ventana, os muestro cómo luce en su versión en inglés ;-)

imageBuscando un poco de información, parece ser que se trata de un problema que aparece al editar el archivo .aspx mientras se está depurando la página, siguiendo una secuencia determinada.

Una de las formas de solucionarlo es un poco bestia, pero funciona (al menos en VS 2008): basta con eliminar el archivo xx.designer.cs indicado por el error (previo backup, por si acaso, aunque hasta ahora no me ha hecho falta nunca ;-)) y forzar al entorno a que lo genere de nuevo, pulsando el botón derecho del ratón sobre el archivo .aspx y seleccionando la opción “Convertir en aplicación web” que habrá aparecido en el mismo.

De momento no le he visto contraindicaciones, y estoy de lo más contento :-)

Publicado en: Variable not found.
lunes, 25 de enero de 2010
La nueva versión de ASP.NET viene cargadita de novedades orientadas a la optimización en motores de búsqueda. Si sabemos aprovecharlas, nuestros sitios webs serán mejor indexados en los buscadores, seremos más fácilmente localizables desde estas herramientas y, consecuentemente, podremos aspirar a tener mayor número de visitantes.

En este post resumiré las mejoras introducidas en  ASP.NET 4 que pueden ayudarnos en nuestra relación con los motores de búsqueda. No son novedades revolucionarias, puesto que todo lo que nos ofrecen podíamos conseguirlo con las versiones anteriores de ASP.NET de alguna u otra manera, aunque sin duda que nos facilitarán algo las cosas. :-)

Page.MetaDescription y Page.MetaKeywords

Descripción y tags en ASP.NET ASP.NET 4 incorpora a la clase Page las propiedades MetaDescription y MetaKeywords para facilitarnos el acceso a la metainformación de la página.

Con la primera de ellas, MetaDescription , podemos especificar en cada página una descripción individualizada, que será utilizada por los buscadores como un resumen de su contenido. Por ejemplo, Google, la incluye como parte de los resultados de las búsquedas.

La segunda, MetaKeywords, permite añadir tags o palabras clave que puedan ser útiles para clasificar su contenido. Aunque la mayoría de los buscadores no utilizan esta información a efectos de indexado, al parecer algunos sí lo hacen, por lo que sigue siendo costumbre incorporar esta información.

En ambos casos podemos establecer su contenido de forma declarativa, en las directivas de la página, así:

<%@ Page Title="Variable not found" Language="C#" 
         MasterPageFile="~/Blog.master" AutoEventWireup="true"
         CodeBehind="Default.aspx.cs" Inherits="Variable.Blog" 
         MetaDescription = "Variable not found. Artículos, noticias, curiosidades, 
                            reflexiones... sobre el mundo del desarrollo de software, 
                            internet, u otros temas relacionados con la tecnología"
         MetaKeywords = "desarrollo,programación,.net,c#,asp.net,asp.net mvc,software"   
%>

Pero también, y esta posibilidad es bastante más interesante, podemos establecerlas mediante código, por ejemplo en el Page_Load(), lo que puede ser útil si por ejemplo tenemos que obtener valores desde una base de datos o similar:

protected void Page_Load(object sender, EventArgs e)
{
   Product prod = ObtenerProducto(); // Carga el producto 
 
   this.Title = prod.Denominacion;
   this.MetaDescription = prod.DescripcionBreve;
   this.MetaKeywords = prod.Tags;
}

En cualquiera de los casos, el resultado es el mismo. ASP.NET, a la hora de generar la página, añadirá en la sección <head> de la página una etiqueta <meta> con la descripción y etiquetas proporcionadas:

<title>NETBOOK ACER ASPIRE ONE D250-0BK</title>
<meta name="description" content="Netbook con procesador Intel® Atom N270 1.6 GHz, 
                                  1GB memoria, 160GB disco duro, t. gráfica Intel® GMA 950,
                                  pantalla 10.1' LED, webcam y Windows XP." />
<meta name="keywords" content="Netbook, ultraportátil, acer, aspire" />

Ni que decir tiene que la etiqueta <head> de la página (o la master que utilice) debe tener el correspondiente runat="server" para que pueda ser modificada en tiempo de servidor.

Response.RedirectPermanent()

Redirecciones 301 en ASP.NET 4 Los más viejos del lugar recordarán que Response.Redirect() está con nosotros desde los tiempos del ASP tradicional, y desde entonces ha mantenido su función: enviar al agente de usuario un resultado HTTP 302, apuntándole una nueva dirección URL en la que localizar el recurso solicitado. Vamos, lo que toda la vida hemos llamado redirección. :-)

Sin embargo, el código de estado 302 definido por el protocolo indica, literalmente, que el recurso solicitado ha sido localizado pero que se encuentra en otra dirección (retornada como información adicional a la respuesta) aunque sólo temporalmente. Por ello se dice que estas redirecciones son transitorias; el navegador (o los robots de búsqueda, en el caso que nos ocupa) no pueden asegurar que la URL indicada sea la ubicación correcta y permanente del recurso.

El código HTTP 301, sin embargo, indica que el recurso solicitado ha sido movido de forma permanente a la dirección que se retorna al agente de usuario. Esto podría ser útil, por ejemplo, si modificamos los dominios sobre los que corre un sitio web, o cambiamos el esquema de URLs que estamos utilizando y, entre otras cosas, quisiéramos aprovechar la información la información que ya tienen los buscadores sobre nuestro sitio.

Pues con este propósito ha sido incluido el método Response.RedirectPermanent()cuya forma de utilización es idéntica a las redirecciones habituales:
 
public partial class About: System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
   {
      // Redirigimos About.aspx a AcercaDe.aspx
      Response.RedirectPermanent("AcercaDe.aspx"); // 301 al canto!
}
}

¡Direcciones amigables!

Routing en ASP.NET 4 ¡Ya era hora de que ASP.NET ofreciera un mecanismo integrado para generar URLs amigables! El motor de routing introducido con ASP.NET 3.5  SP1 tan magníficamente aprovechado en el framework MVC, toma ahora su protagonismo también en el mundo de Webforms. Y la forma de usarlo, igual de sencilla. :-)

Para que nuestra aplicación soporte friendly urls, tenemos que registrar durante la inicialización del sistema las rutas, o mejor dicho, el patrón del URLs, que vamos a entender. Por ejemplo, imaginemos que nuestra aplicación, un catálogo on-line, debe atender peticiones a direcciones como las siguientes para mostrar la página de detalle de un producto:
Esto podríamos conseguirlo durante la inicialización del sistema, registrando un patrón de ruta de la siguiente forma, en el global.asax:

void Application_Start(object sender, EventArgs e)
{
   // Code that runs on application startup
   RegistrarRutas();
}
 
private void RegistrarRutas()
{
   RouteTable.Routes.MapPageRoute(
      "DetalleProducto",       // Nombre de la ruta
      "product/{productCode}"// patrón de URL
      "~/product.aspx"         // Página que procesará la petición
);
}

Lo que indica la ruta es que las direcciones de tipo product/{productCode} serán enviadas a la página física ~/product.aspx. La porción variable de la URL, el parámetro {productCode} podremos obtenerlo desde el código de la página para cargar los datos desde el almacén correspondiente, por ejemplo así (en product.aspx.cs):

public partial class Product : System.Web.UI.Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      string productCode = RouteData.Values["productCode"] as string;
      if (!cargaProducto(productCode))
      {
         Response.Redirect("ProductNotFound.aspx");
      }
   }
}

Como puede intuirse, a través de la colección RouteData.Values podremos acceder a los parámetros suministrados en el interior de la ruta, es decir, los que forman parte de la URL de la página que introduce el usuario.

Al igual que ocurre en ASP.NET MVC, el sistema de rutas es bidireccional, por lo que podremos también generar links ‘amistosos’ hacia recursos del sitio web, como en el siguiente ejemplo:

HyperLinkToAcerAspire.NavigateUrl = 
      GetRouteUrl("DetalleProducto", 
                   new { productCode = "ACER-ASPIRE-ONE-D250-0BK" }
);

El método GetRouteUrl() genera la URL del producto utilizando el propio motor de routing, para lo que le pasamos el identificador de la ruta y, en un objeto anónimo, el valor para el parámetro requerido (productCode). El resultado para el caso anterior será la dirección: /product/ACER-ASPIRE-ONE-D250-0BK.

Mejoras en el marcado

Aunque no vamos a detallarlas, o al menos en este post ;-), aparecen también en ASP.NET 4 un buen conjunto de novedades dirigidas a mejorar la calidad del marcado que enviamos a cliente. Y dado que siempre se ha dicho que un marcado respetuoso con los estándares es bueno para el SEO, estas nuevas capacidades del framework nos ayudarán también a mejorar nuestro posicionamiento.

Publicado en: Variable not found.
miércoles, 20 de enero de 2010
¿Se pierde el Referer al cambiar el location.href? El HTTP Referer es una variable que nos envían los navegadores en cada petición, permitiéndonos conocer de dónde viene el usuario, es decir, la página donde se encontraba el enlace, botón o formulario cuya activación ha provocado el salto a nuestro sitio.

Por ejemplo, si un servidor recibe esta solicitud:

GET / HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, (...omitido...), */*
Referer: http://www.google.es/search?hl=es&rls=ig&q=variable&btnG=Buscar&meta=&aq=f&oq=
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; (...omitido...) )
Accept-Language: es
Accept-Encoding: gzip, deflate
Host: www.variablenotfound.com
Connection: Keep-Alive

analizando el campo Referer se puede determinar de forma muy sencilla que se trata de un usuario que proviene de Google, y que estaba buscando el término “variable”. Esta característica aporta una información, que aunque no es demasiado fiable (se puede alterar y desactivar muy fácilmente),  se utiliza con mucha frecuencia con fines estadísticos, o para adecuar el contenido de la página a las intenciones del usuario.

Sin embargo, como se trata de una característica manejada directamente por el navegador, podemos encontrarnos con que no todos actúan de la misma manera... o en otras palabras, es Internet Explorer es el que actúa de forma diferente al resto ;-)

Si la visita a nuestra página se produce como consecuencia de la ejecución de un script que ha modificado dinámicamente el location.href, o ha invocado a location.replace, Internet Explorer saltará a la nueva dirección, pero no enviará el Referer en los encabezados de la petición, por lo que en el punto de destino no se podrá conocer el origen de la misma.

Por tanto, un código como el siguiente hará que la página editar.asp no pueda conocer desde dónde se le ha referenciado:

<input type="button" value="editar" onclick="location.href='editar.asp';">

Dado que Microsoft todavía está considerando modificar este comportamiento, hay que darle un poco las vueltas para conseguirlo provocando el salto hacia la página de destino sin utilizar los mecanismos citados anteriormente.

Una forma muy ingeniosa que he encontrado se basa en crear dinámicamente un tag <a> con su correspondiente href establecido, y simular la pulsación del mismo invocando al evento click:

function navigateWithReferrer(url) {
   var fakeLink = document.createElement("a");
   if (typeof (fakeLink.click) == 'undefined')
      location.href = url; 
      else {
         fakeLink.href = url;
         document.body.appendChild(fakeLink);
         fakeLink.click();   
      }
}

Visto en: Velocity Reviews
Publicado en: Variable not found
domingo, 17 de enero de 2010
Un truco rápido para poder utilizar el magnífico Fiddler mientras estamos desarrollamos con Visual Studio y utilizando el servidor web integrado. Como habréis comprobado, al ejecutar una solución se inicia el servidor de desarrollo y se abre la ventana apuntando a “localhost:puerto/página”, y dichas peticiones por defecto no son capturadas por esta herramienta.

Aunque existen distintas formas para conseguirlo (algunas de ellas descritas en la propia web del producto), hay una que es realmente sencilla, no hay que configurar nada, y es bastante rápida de activar:

Incluir un punto después de “localhost” en la ventana del navegador cuya sesión vamos a depurar
image

Publicado en: Variable not found.

martes, 12 de enero de 2010
Montar un disco duro virtual .vhd como si fuera un disco físico de nuestra máquina puede resultar muy interesante para acceder a archivos contenidos en el mismo sin necesidad de tener que adjuntarlo a una máquina virtual.

Ya comenté hace unas semanas que en Windows 7 y 2008 esta operación puede hacerse directamente desde la consola de administración de discos del propio sistema operativo, pues es un formato aceptado de forma nativa por éstos. Sin embargo, en equipos corriendo Windows XP ó Vista, el procedimiento se complica un pelín más, puesto que hay que instalar un software que permita al sistema operativo reconocer el archivo .vhd como un disco duro adicional. Veamos cómo conseguirlo.

imageAunque existen otras alternativas, utilizaremos una solución muy sencilla que se distribuye como parte del producto gratuito Virtual Server 2005 R2, que tendremos que descargar desde la web de Microsoft. Obviamente, no instalaremos el producto completo, sólo lo estrictamente necesario para lograr el fin propuesto.

Una vez en nuestro equipo, iniciamos la instalación como habitualmente. Tras aceptar la licencia de uso, sin leerla, faltaría más ;-P, es importante elegir la instalación personalizada e indicar en cada uno de los componentes que no deseamos instalarlo. Bueno, en todos excepto en el llamado “Montaje de VHD”, que es precisamente lo único que nos interesa del producto en este momento.

Una vez completada la instalación, por ejemplo sobre “c:\archivos de programa\microsoft virtual server”, en su interior podremos encontrar una carpeta llamada “Vhdmount” en la que encontraremos la herramienta que andábamos buscando.

La forma de utilizarla, así de sencillo:
vhdmount.exe /p /f "d:\Virtual\JMA.VHD"
A partir de ese momento, el disco duro estará disponible en Mi PC, como si se tratara de un disco físico más. Y cuando queramos desconectarlo,
vhdmount.exe /d "d:\Virtual\JMA.VHD"
Pero si lo que quieres es simplificar aún más esta tarea, David Cervigón aportó hace ya bastante tiempo una solución que añade las órdenes de montado y desmontado al menú contextual del explorador de Windows:
 Montado y desmontado de discos virtuales

Publicado en: Variable not found
lunes, 11 de enero de 2010
Ya iba siendo hora de estrenarme este 2010 y,image como ordena la tradición, el primer post del nuevo año lo reservo para comentar las entradas que han sido más populares a lo largo del año que acabamos de cerrar.

Esta vez voy a introducir una novedad en el análisis, separando los posts que han sido escritos durante este año de otros, creados años anteriores y que todavía gozan de gran popularidad en la red.

Cosecha de 2009

Encabezando el top ten aparece “101 formas de saber que tu proyecto está condenado al fracaso”, una traducción autorizada del original 101 Ways To Know Your Software Project Is Doomed de Max Pool, que enumeraba, en clave de humor, una serie de pistas para saber si un proyecto se estaba precipitando hacia un estrepitoso fracaso.

Seguido de cerca tenemos “ASP.NET MVC: trece preguntas básicas”, un pequeño resumen de cuestiones realizadas muy frecuentemente tras el primer encuentro con el framework, como qué es MVC, qué ventajas tiene sobre Webforms, o si vale la pena pasarse a esta nueva forma de desarrollar aplicaciones web.

En tercer lugar, “Y todavía otras 101 citas célebres del mundo de la informática”, la tercera entrega de un clásico de este blog, con otras ciento una frases recogidas sobre este mundillo. En total, 303 frases, no está mal.

A continuación, el post “jqGrid: Grids espectaculares para ASP.NET MVC, paso a paso” ha demostrado el interés que despierta el uso de este plugin para mostrar y editar datos tabulados en el framework ASP.NET MVC.

En quinta posición tenemos la serie de tres posts “C#: Desmitificando las expresiones lambda” con la que pretendí quitar un poco de misterio a las expresiones lambda, esa fascinante y temida característica de la última hornada de nuestro lenguaje favorito.

En el post “Aspectos a tener en cuenta al crear sitios web públicos” recopilé las opiniones de un hilo de StackOverflow en el que se debatía sobre aquellos aspectos que teníamos que considerar, desde el punto de vista técnico, para crear webs destinadas al público en general, clasificadas por categorías como experiencia de usuario, seguridad, rendimiento, SEO, etc.

En séptima posición, “Plantillas de proyectos ASP.NET MVC 1.0 para NUnit”, donde se describían los pasos para instalar NUnit como framework de pruebas unitarias en proyecto ASP.NET MVC.

La octava posición es para “Indicios de que tu interfaz de usuario fue creado por un programador”, que comentaba y ampliaba el post de Ian Voyce “The 7 signs your UI was created by a programmer” sobre los rastros que dejamos los desarrolladores cuando queremos hacer de diseñador.

En penúltima posición, “Generación de PDF desde .NET usando formularios”, donde describía un truco muy rápido para generar documentos PDF al vuelo, utilizando formularios en el documento y la librería iTextSharp para rellenar su contenido.

En décima posición, “Programadores con producción neta negativa (NNPP)”, post donde comentaba el curioso fenómeno de la existencia de desarrolladores cuyo saldo en las aportaciones a un proyecto resultara negativo, o sea, que el valor de su producción fuera superado por el coste de los errores y defectos que introducían en las aplicaciones.

Cosechas anteriores

En este apartado encontramos los posts que podríamos considerar clásicos en este blog, pero dado que muchos de los lectores acaban de llegar, no está de más comentar su existencia.
Las dos primeras posiciones, un año más como líderes indiscutibles, citados, copiados y pegados hasta la saciedad, “Otras 101 citas célebres del mundo de la informática” y “101 citas célebres del mundo de la informática”.

En tercera posición, “Bordes redondeados en webs (sin esfuerzo) con Nifty Corners Cube”, un post de 2007 donde comentaba el uso de esta librería de scrips para redondear las esquinas de elementos de bloque en páginas web.

Le sigue otra creación de 2007, “Evitar el postback al pulsar un botón en ASP.Net”, donde comentaba distintas formas de hacer que no se lanzara un postback al pulsar un botón incluido en una página ASP.NET, utilizando, por ejemplo, para evitar envíos múltiples de un formulario.

Otro de los grandes clásicos, en “13 Consejos para comentar tu código” comentaba una serie de prácticas destinadas a facilitar la legibilidad en el código fuente.

La sexta posición la ocupan las “32 técnicas de producción de ideas”, un resumen de un post de Neuronilla sobre técnicas destinadas a favorecer la creatividad.

El post “Llamar a servicios web con ASP.NET AJAX paso a paso”, donde se describe detalladamente cómo utilizar ASP.NET AJAX para obtener datos desde un servicio web.

En octava posición, curiosamente, un post sobre el “Escaneo de puertos con idle scan”, una ingeniosa técnica para detectar puertos abiertos en máquinas remotas utilizando un equipo zombie que oculta la identidad del atacante.

“20 desastres famosos relacionados con el software” traducción autorizada por Timm Martin de su serie “20 Famous Software Disasters”, que recogía un buen número de casos en los que fallos relacionados con el software habían tenido consecuencias trágicas.

Por último, “Enviar mensajes con imágenes incrustadas desde .NET”, de la cosecha de 2008, donde se mostraba cómo incrustar archivos de imagen en un mensaje de correo electrónico generado desde una aplicación .NET.

¡¡Feliz 2010!!

Publicado en: Variable not found.