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!
viernes, 5 de febrero de 2010
ASP.NET MVC 2 RC 2Hace unas horas Phil Haack ha anunciado la publicación de la penúltima revisión del framework MVC 2 antes de la versión final.

Según se recoge en el documento de notas de la revisión, la única característica añadida ha sido el cambio en la forma de validar las entidades del Modelo. En versiones anteriores, durante el binding se evaluaban las restricciones establecidas en las propiedades cuyos valores eran recibidos por el servidor, mientras que ahora se valida la entidad completa.

También, aunque de menor calado, han sido introducidos otras mejoras interesantes, como el nuevo método Peek() del diccionario TempData, el incremento del rendimiento en varios puntos, o una nueva forma de indicar parámetros opcionales en las rutas, que son eliminados para no interferir otros datos recibidos en la petición.

Desafortunadamente, aún no podemos probarla con las versiones preliminares de VS2010, y sólo funcionará con la versión 2008 del IDE. :-(

Enlaces:
Publicado en: Variable not found.
miércoles, 3 de febrero de 2010
Mi gran descubrimiento del día probablemente será una chorrada para la inmensa mayoría, pero también seguro que hay alguien que, como un servidor, no se había percatado hasta el momento de este detalle de IE8.

Como sabéis, la barra de direcciones de este navegador nos permite escribir la URL de la página que queremos visitar, pero podemos ahorrar mucho tiempo si tecleamos únicamente algunos caracteres contenidos en la misma: Internet Explorer buscará en el historial de sitios visitados y en los favoritos, mostrando aquellos sitios que contengan la cadena buscada.

Por ejemplo, escribiendo “vari”, mi Explorer 8 muestra las siguientes sugerencias:

IE8 sugiriendo sitios que contienen el texto "vari"
Sin embargo, si alguna vez introducís una dirección incorrecta, por ejemplo tecleando un carácter de más, u omitiendo alguno, esta URL será añadida al historial, y se mostrará como sugerencia también, efecto bastante incómodo.

En la captura anterior, se puede ver que Internet Explorer ofrece “varialablenotfound.com”, una dirección que tecleé de forma incorrecta tiempo atrás.

Pues mi gran descubrimiento es este: si paseamos el ratón sobre esta sugerencia, o la seleccionamos usando la tecla flecha abajo, aparece a la derecha un icono que nos permite eliminarla, para que no nos moleste más:

Icono para eliminar la entrada de las sugerencias
La explicación de que no lo haya visto hasta ahora es muy sencilla: al aparecer a la derecha del desplegable queda fuera del foco de atención en ese momento, que está justo en el lado contrario, y especialmente en pantallas con resolución muy ancha.

Por curiosidad he probado a ver si existía algo parecido en Chrome, Firefox y Opera, y ninguno incluye este detalle, que nos viene de perlas a los que somos algo muñones ;-)

Publicado en: Variable not found.
lunes, 1 de febrero de 2010
aspnetmvc Con objeto de mejorar la seguridad de nuestras aplicaciones, la Release Candidate de ASP.NET MVC 2 introdujo un cambio importante en la forma de procesar peticiones que retornan información serializada como JSON: por defecto, ahora sólo se responde a peticiones de tipo POST.

Dado que en MVC 1.0 era justo al contrario, esta pequeña reorientación hace que aplicaciones que antes funcionaban correctamente dejen de hacerlo al migrarlas a la última versión del framework. Un ejemplo lo tenemos con las aplicaciones que aprovechan la potencia de jqGrid para mostrar y editar rejillas de datos. Recordemos que el intercambio de información entre cliente y servidor se realiza mediante llamadas Ajax que retornan siempre datos en notación JSON.

Los síntomas que notaremos en estos casos son muy simples: ¡las acciones que deberían devolvernos información dejan de hacerlo! En algunas ocasiones, dependiendo del uso que se dé en la vista a la la información retornada, es posible que aparezcan errores de script en el navegador, pero otras ni siquiera eso.

En cualquier caso, no es difícil dar con la solución. Con Firebug, Fiddler, o cualquier herramienta que nos permita monitorizar las peticiones, podremos observar que en la petición Ajax se está produciendo un error HTTP 500 (error interno de servidor):

image

Y si seguimos profundizando en dicha petición, podemos ahora conocer el mensaje descriptivo que envía el servidor, un auténtico detalle por parte del equipo de desarrollo de ASP.NET MVC 2, en el que incluso nos indican la solución al problema:

<html>
<head>
<title>This request has been blocked because sensitive 
information could be disclosed to third party web sites when 
this is used in a GET request. 
To allow GET requests, set JsonRequestBehavior to AllowGet.</title>
<style>

Ante esta situación, podemos optar por dos soluciones. La primera sería indicar explícitamente en la instancia del resultado, de tipo JsonResult, que queremos permitir el método GET, así:

return Json(data, JsonRequestBehavior.AllowGet);

Y otra posibilidad sería realizar las peticiones Ajax utilizando el método POST, algo que podemos conseguir muy fácilmente la mayoría de las veces. En el caso de los ejemplos con jqGrid, sería sustituyendo el ’GET’ por ‘POST’ en código:

[...]
jQuery("#list").jqGrid({
url: '<%= Url.Action("ObtenerDatosGrid") %>',
datatype: 'json',
mtype: 'POST',    // <- Aquí
colNames: ['Apellidos', 'Nombre', 'Fecha Nac.', 'Email'],
[...]

¡Gracias, Maxi, por los comentarios que inspiraron este post!

Publicado en: Variable not found.
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