Cómo simular otros navegadores para probar desarrollos Web

Post original en JASoft.org: http://www.jasoft.org/Blog/post/Como-simular-otros-navegadores-para-probar-desarrollos-Web.aspx

En ocasiones es muy útil poder engañar al servidor web y hacerle creer que te estás conectando con cualquier navegador, aunque en realidad estés usando Internet Explorer o Chrome bajo Windows, por ejemplo.

Como sabes, los controles de ASP.NET Web Forms tienen lo que se llama renderizado adaptativo, que consiste en que generan un HTML diferente según el dispositivo que solicite la página, pudiendo así adaptarse a las características de cada navegador de la mejor forma posible.

Así puedes ver qué efecto causa sobre el HTML que renderiza tu aplicación si estás usando un navegador muy viejo (Netscape?) o saber si cambia según sea el sistema operativo (puedes decir que estás trabajando desde Linux o Mac aunque estés en Windows), etc.. Un caso muy habitual es, por ejemplo, si estás probando una aplicación móvil y quieres ver qué HTML te devolvería cuando te conectas con un iPhone o un Windows Phone, puedes engañar al servidor fácilmente y hacerte pasar por uno de estos navegadores simplemente cambiando el User-Agent.

Obviamente el HTML no se interpretará como si fueras uno de esos navegadores, sin que seguirá siendo el motor de tu navegador el que renderice las páginas, así que que no te permite simular a otros navegadores, sólo te permite indicar otro agente de usuario para ver qué HTML te devuelve exactamente la aplicación en función del navegador que utilices.

La buena noticia es que como la mayoría de los navegadores de moviles son muy compatibles con HTML5 en lo que se refiere a maquetado de la página y sus funciones principales el motor de renderizado de IE9 te servirá para obtener una representación bastante fiel de cómo se verá en los  navegadores móviles reales. Si además le cambias el tamaño a la ventana para que tenga las dimensiones de la pantalla de un móvil o tablet será más fiel todavía:

  • 640×960 en el caso de un iPhone
  • 1024×768 en un iPad
  • 1024×600 en un Samsung Galaxy Tab con Android
  • 480×800 en un típico terminal con Android (HTC Sensation, HTC Desire, Samsung Galaxy S y SII)
  • 1280×800 en un Samsung Galaxy Note de 5,3» con Android (¡impresionante!)
  • 480×800 si es cualquier Windows Phone

En esta página puedes encontrar las resoluciones de la mayoría de los modelos de móviles en el mercado.

Cómo simular cualquier agente de usuario con Internet Explorer

El navegador del mercado que mas nos facilita hoy en día el hacer este cambio es Internet Explorer. Para conseguirlo basta con acudir a las herramientas del programador (pulsar F12 cuando estés con cualquier página abierta). Una vez en ellas vamos al menú Herramientas y vemos que hay una opción precisamente para ello, que ya trae además configurados los agentes de usuario de los navegadores de escritorio más comunes:

IE_CambiarUserAgent

Así podemos simular rápidamente a Google Chrome, versiones antiguas de Internet Explorer, Opera, la araña/robot de búsqueda de Bing…

También podemos añadir cadenas propias a la colección "Custom" y tenerlas ahí guardadas para reutilizar:

IE_CustomUA

En Internet hay multitud de listas con las cadenas de agente de usuario de cientos de navegadores, pero a mi me gusta especialmente esta de Zytrax. No es muy bonita ni fácil de buscar pero creo que es bastante certera.

En otros navegadores (Firefox y Chrome) es posible cambiar también este ajuste pero no es ni de lejos tan cómodo e inmediato.

¡Espero que te sea útil!

Cómo obtener rutas absolutas en ASP.NET

Post original en JASoft.org: http://www.jasoft.org/Blog/post/Como-obtener-rutas-absolutas-en-ASPNET.aspx

RutaHoy un truco rápido.

En ASP.NET a veces necesitamos convertir rutas relativas (por ejemplo guardadas en una base de datos) a rutas absolutas para poder referenciar archivos para descarga, imágenes, etc…

Estas rutas pueden venir dadas de diversas formas. Por ejemplo, todas estas son rutas válidas:

  • "/Docs/doc.pdf": se refiere a la raíz absoluta del servidor, es decir desde el nombre de dominio en adelante.
  • "../Img/image.jpg": ruta relativa a la página actual, un directorio por encima.
  • "./files/features.js": se refiere a una ruta dentro de la carpeta que contiene a la página actual.
  • "~/CSS/styles.css": ruta relativa a la raíz de la aplicación, que no tiene porqué coincidir con la raíz del servidor ya que puede que nuestra app cuelgue de una carpeta virtual, por ejemplo. Esto es algo que no siempre es tenido en cuenta.

Y hay más combinaciones posibles, como por ejemplo el uso de los ../ por el medio de la propia ruta, etc…

A veces con esto es suficiente porque el dato que tenemos almacenado se refiere a la página actual, pero no necesariamente es siempre así y nos vendrá bien convertirlo en una ruta absoluta, que incluya el nombre del servidor, el puerto, el protocolo, etc…

Sería relativamente fácil crear una función que tuviera en cuenta todas las casuísticas y nos transformara la cadena en una ruta absoluta, pero por suerte ASP.NET ya trae de serie una funcionalidad así.

Recientemente me encontré con esta necesidad a la hora de transformar rutas que en su mayoría comenzaban con el carácter especial "~" que marca el directorio raíz de la aplicación. En este caso es especialmente importante transformar la ruta ya que esta notación sólo es entendida por ASP.NET y si le ponemos una ruta así a algo que enviemos al navegador, éste no sabrá interpretarlo.

¿Cuál es el código que utilicé?. El siguiente:

   1: public string ConvertRelativeUrlToAbsoluteUrl(string relativeUrl)

   2: {

   3:     if (Request.IsSecureConnection)

   4:         return string.Format("https://{0}{1}{2}", Request.Url.Host, 

   5:             Request.Url.Port == 80 ? "" : ":" + Request.Url.Port.ToString(), 

   6:             Page.ResolveUrl(relativeUrl));

   7:     else

   8:         return string.Format("http://{0}{1}{2}", Request.Url.Host,

   9:             Request.Url.Port == 80 ? "" : ":" + Request.Url.Port.ToString(),

  10:             Page.ResolveUrl(relativeUrl));

  11: }

Como puedes ver es muy sencillo, pero tiene en cuenta si la URL es segura o no (con SSL), si el puerto utilizado es el estándar (80) o no, etc…

¡Espero que te resulte útil!

Establecer correctamente DefaultButton y DefaultFocus en una página con Master Page

Post original en JASoft.org: http://www.jasoft.org/Blog/post/Establecer-correctamente-DefaultButton-y-DefaultFocus-en-una-pagina-con-Master-Page.aspx

En ASP.NET Web Forms algunos controles disponen de un par de propiedades interesantes para mejorar la usabilidad de la interfaz de usuario. Se trata de DefaultButton y DefaultFocus que permiten decidir respectivamente qué botón del formulario va a ser el que se ejecute al pulsar ENTER y qué control tendrá el foco en el formulario cuando éste cargue.

Esto, que parece una tontería, es muy útil ya que es frecuente encontrarse por ahí páginas bastante mal hechas en las que, por ejemplo, vas a buscar algo en un cuadro de búsqueda, le das a ENTER tras introducir los términos de búsqueda en el cuadro de texto correspondiente, y en lugar de efectuarse la búsqueda lo que ocurre es que simplemente se recarga la página. El motivo es que cuando pulsas ENTER en un cuadro de texto, por defecto lo que hace cualquier navegador es enviar el formulario al servidor. Si resulta que tu código de búsqueda está en el evento Click de un botón o un ImageButton, no se lanza este evento de servidor y por lo tanto la búsqueda no se realiza. Es muy frustante.

Lo que deberíamos hacer normalmente si no existiese la propiedad DefaultButton es capturar con JavaScript el envío del formulario y sustituirlo por una llamada a la función __doPostBack que genera el evento. Un engorro absoluto para algo que debería ser inmediato. Gracias a DefaultButton basta con indicar en esta propiedad el nombre del botón deseado, y cuando se pulse ENTER estando en cualquier cuadro de texto contenido en el control en el que hemos establecido la propiedad, en lugar de enviar el formulario se lanza el evento de este botón. Fácil.

Lo mismo ocurre con el cuadro de texto o control de formulario que en el que queramos que recaiga el foco al entrar en la página. Es bastante molesto, por ejemplo, entrar a una página en la que nos solicitan unos datos y tener que pulsar con el ratón en el primer cuadro de texto libre para poder empezar a escribir. Lo suyo sería que el foco ya estuviese en el primer control automáticamente. De nuevo, conseguirlo con JavaScript es sencillo pero engorroso si tuviésemos que hacerlo en todas las páginas. Si establecemos la propiedad DefaultFocus al nombre del TextBox que queramos, ya se ocupa ASP.NET de hacerlo.

Fíjate en que estas dos propiedades, aunque se suelen aplicar en el formulario que tienen todas las páginas ASP.NET Web Forms, en realidad se puede utilizar con otros controles contenedores, fundamentalmente el control Panel, si bien cualquiera que herede de la clase Container lo posee. Según Reflector estos son los controles que lo implementan:

DefaultButton_DefaultFocus_Controles

 

Lo normal, como digo, es aplicarlo en el propio formulario de la página:

DefaultButton_DefaultFocus

o en un control Panel que contenga controles para toma de datos.

Por ejemplo, si tenemos un formulario de búsqueda con un control Textbox llamado txtTextToSearch y un botón llamado btnSearch, podríamos establecer estas propiedades en el formulario de esta manera:

   1: <form id="form1" runat="server" defaultbutton="btnSearch" defaultfocus="txtTextToSearch">

De esta forma al cargar la página el foco estará en el cuadro de texto y cuando escribamos algo en él y pulsemos ENTER se lanzará el evento Click del botón. Estupendo.

Controles dentro de Páginas Maestras (Master Pages)

Esto es estupendo en una página individual «suelta» y funciona muy bien. Pero lo normal es que en cualquier aplicación Web no trivial estemos utilizando Master Pages (a mi lo de llamarles Páginas Maestras me repele, prefiero el término en inglés o simplemente «plantillas»).

Al utilizar una MP, las páginas derivadas no tienen ya un formulario, puesto que éste está en la plantilla y no en la página en sí, por lo que no podemos aplicarle estas dos propiedades directamente.

Para solucionar el problema con controles que tengamos en nuestra página derivada tenemos dos opciones bastante sencillas a priori:

  1. Utilizar un control Panel para envolver a nuestros controles y establecer la propiedad allí.
  2. Utilizar la propiedad Page.Form para acceder al formulario principal, y establecer por código DefaultButton y DefaultFocus desde el evento Load de la página.

Así, por ejemplo, podríamos intentar escribir esto:

   1: Page.Form.DefaultButton = btnLogin.ID;

El problema es que no funcionaría.

Lo que está ocurriendo es que cuando la página no deriva de una Master Page podemos simplemente establecer estas propiedades con el identificador de los controles. Pero cuando una página utiliza una MP, lo que ocurre internamente es que se genera una jerarquía más compleja en la que el contenido de la Master se convierte en un control hijo del Web Form que contiene a sus controles ContentPlaceHolder, y éstos a su vez contienen a los controles que hayamos puesto dentro de ellos al diseñar la página.

En cristiano: si el control se llamaba «btnSearch» cuando la página estaba sola, cuando utilizamos una Master Page su nombre en el lado cliente se convierte en algo similar a esto:

  ctl00$ContentPlaceHolder1$pnlSearch$btnSearch

por ejemplo, en el caso de que el botón esté dentro de un panel, que a su vez esté en un ContentPlaceHolder y este último, por supuesto, dentro de una Master Page.

Este es el valor que tendrá en el atributo «name» del control HTML correspondiente en el código fuente que se genera para la página. Pero es que en el atributo «id», lo que tendrá será algo similar a esto:

ctl00_ContentPlaceHolder1_pnlSearch_btnSearch

Por lo tanto lo que tenemos que hacer en estas propiedades es indicar el nombre correcto de lado de cliente, que no es el identificador del botón o control.

Y ¿cuál es el nombre correcto en cada caso y cómo lo obtenemos?

Podremos obtener el valor del atributo «id» usando la propiedad ClientID del control. El valor del atributo «name» se obtiene a través de la propiedad UniqueID del mismo.

Por lo tanto, en nuestro ejemplo, bastaría con escribir esto en la carga de la página:

   1: Page.Form.DefaultButton = btnSearch.UniqueID;

   2: Page.Form.DefaultFocus = txtTextToSearch.ClientID;

Fíjate que en cada caso debemos usar una propiedad diferente para obtener un identificador diferente. Esto es así porque en el caso del botón se utiliza su identificador para localizarlo en la página (con getElementById), mientras que en el caso del cuadro de texto se localiza dentro de los controles del formulario mediante su nombre (contenido en el atributo «name»).

¡Espero que te sea útil!

¿Te ha gustado este post? – Aprende .NET con los cursos on-line tutelados de campusMVP:
   ·
Preparación del examen 70-515: Desarrollo Web con .NET 4.0 (Tutelado por mi)
   · Desarrollo Web con ASP.NET 4.0 Web Forms (Tutelado por mi)
   · ASP.NET 4.0 Web Forms desde cero (Tutelado por mi)
   · Desarrollo Web con ASP.NET MVC 3 
   · Silverlight 4.0 – Aplicaciones Ricas para Internet (RIA)
   · jQuery paso a paso para programadores ASP.NET
   · Visual Studio 2010 desde cero

Plantillas de lado cliente con Java Script ¿Qué tecnología utilizar?

Post original en JASoft.org: http://www.jasoft.org/Blog/post/Plantillas-de-lado-cliente-con-JavaScript-191;Que-tecnologia-utilizar.aspx

asp-net-ajaxEn septiembre de 2009 Krasis Press lanzó al mercado mi libro “Tecnologías ASP.NET 4.0 (Saltando desde la versión 2.0)”. Fue un libro que se adelantaba en varios meses a la futura versión de la plataforma y el entorno de desarrollo. En el momento de escribirlo, en Julio de 2009, las últimas noticias sobre el lanzamiento del producto apuntaban a Octubre de 2009, y que muy pocos cambios iban a aparecer en la versión final. Por ello, a pocos meses vista de esa versión definitiva, aún con la Beta 1 de la plataforma, nos decidimos a lanzarlo al mercado.

Trabajar con las Betas de Microsoft tiene muchas ventajas, pues te permite estar al cabo de la calle y adelantarte al mercado en las tecnologías que vendrán. Pero también tiene algunos inconvenientes, entre ellos que puede haber cambios de última hora que echen a perder el tiempo invertido. Al final, la versión definitiva de .NET 4.0 se fue retrasando y apareció el 12 de Abril de 2010. Este mayor ciclo de vida para las versiones previas del producto hizo que algunas características sufrieran algunos cambios más de los inicialmente esperados. Esto fue precisamente lo que ocurrió con una de las tecnologías más interesantes que aparecían en la parte Web con la versión 4.0: las plantillas de lado de cliente en ASP.NET Ajax Library.

El capítulo 5 de mi libro trata este tema con bastante profundidad. Enseña a utilizar AJAX para producir al vuelo páginas Web enlazadas a datos desde el propio navegador. Esto representa una nueva filosofía de trabajo y proporciona una potencia increíble a los programadores de aplicaciones Web.

Dentro de las cosas que explica ese capítulo 5 se encuentran las plantillas de lado cliente. La idea es la siguiente: tráete los datos desde el servidor llamando a un servicio mediante AJAX y en lugar de cargar otra página o renderizar una vista parcial de la actual 8como hace un UpdatePanel), construye dinámicamente la nueva interfaz para trabajar con los datos. Ello implica entre otras cosas poder definir plantillas HTML para visualizar datos, permitir enlazado a datos con JavaScript entre la interfaz y el modelo JSON, enviar datos automáticamente al servidor para guardar cambios, etc… Es una característica compleja que implica sacar un partido muy grande a un lenguaje como JavaScript. Ni sus padres reconocerían lo que es capaz de hacer hoy en día este lenguaje. De hecho creo que no hay ningún otro libro en el mercado que explique esta tecnología pues en su momento, cuando lo escribí, no había apenas documentación y prácticamente tuve que leerme el código fuente completo para entender cómo diablos funcionaban.

La mala noticia para mi esfuerzo es que en la versión definitiva de ASP.NET 4.0 hubo cambios significativos en cuanto a la biblioteca JavaScript de lado cliente de Microsoft. Entre ellos que ya no se incluía de serie con ASP.NET sino que iba dentro del Control Toolkit, y además había habido algunos cambios menores en la tecnología de plantillas de lado cliente que hacían que lo explicado en el libro no funcionase correctamente. Por ello lancé poco después un apéndice a mi libro (lo puedes leer gratuitamente en este enlace) que explicaba estos cambios y permitía seguir sacando partido a esta tecnología.

¿Qué pasa con la biblioteca de lado cliente de Microsoft?

Recientemente he recibido un correo de un lector de mi libro preguntándome acerca de esta tecnología. Cuando había aprendido sobre ella en el libro le había entusiasmado, pero ahora al ver el pobre soporte que daba Microsoft para la misma estaba decepcionado y no sabía a qué atenerse. Me preguntaba qué le podía recomendar a la hora de crear este tipo de interfaces basadas en código de lado cliente. ¿es interesante seguir usando la tecnología de Microsoft o hay otras alternativas? ¿Qué pasa con jQuery?

Lo diré sin paños calientes: la parte de cliente de ASP.NET AJAX está muerta y no merece la pena invertir en ella. No ocurre lo mismo con la parte servidor, es decir, ScriptManager, UpdatePanel y similares, y los controles del Control Toolkit, que siguen siendo muy útiles.

Nota: otra batalla sería dilucidar si las aberraciones que comente la gente usando el UpdatePanel y compañía compensa la gran utilidad que se les puede sacar a estos controles si se los sabe usar bien. Me hace gracia cuando algunas veces veo aplicaciones Web basadas en ASP.NET AJAX que van lentísimas y los programadores que las han hecho se quejan de la tecnología: No, perdona, esa tecnología es estupenda, pero como no te has preocupado de entender cómo funciona por debajo y las implicaciones que tiene usarla (comprándote mi libro, por ejemplo, donde lo explico con detalle) pues entonces pasa lo que pasa. Antes de echar la culpa a una tecnología primero hay que entenderla bien. Y lo dejo que si no me pierdo 😉

El motivo de que diga esto es que Microsoft quiso hacer unas bibliotecas de lado cliente muy potentes que dejaran hacer muchas cosas, como las plantillas que están en mi libro. Sin embargo, en lugar de apoyar algún proyecto potente y maduro que ya existiera, como por ejemplo jQuery, hicieron su propio sistema. Típico de Microsoft por desgracia.

JQueryUn poco antes de haber sacado .NET 4.0 y VS2010, de repente vieron la luz y decidieron hacer lo que tenían que haber hecho desde el principio: apoyar jQuery y no reinventar la rueda. jQuery es super-potente y está muy probado siendo casi el estándar para desarrollo Web con JavaScript hoy en día. Por lo tanto decidieron no seguir desarrollando su parte de cliente y apoyar a jQuery. Es más, los controles del AJAX Control Toolkit aparte de funcionar en lado cliente con la tecnología de Microsoft, a su vez son todos plugins de jQuery para facilitar su uso desde este framework.

Tanto apoyaron a jQuery que en ese momento decidieron ayudar con el desarrollo de algunas de sus funcionalidades, entre ellas las funcionalidades para plantillas de lado cliente. Además, en lugar de usar lo que ya tenían, hicieron una cosa completamente diferente llamada jQuery Templates.

La verdad es que también estaban muy bien y me ilusionaron durante un tiempo, pero si estás pensando: «estupendo, me va a recomendar usar esto», te diré que NO.

El problema es que la primera beta del proyecto es de marzo de 2010, justo antes de que saliera VS2010, y parecía que iba a muy buen ritmo, pero en abril de 2011 decidieron parar el desarrollo por todos los problemas que tenían. Así que ahora hay dos proyectos oficiales en jQuery destinados a hacer platillas: JSRender y JSViews que trabajan en conjunto para conseguir plantillas de lado cliente. Hoy por hoy, yo no los recomendaría porque están todavía haciendo cambios y de vez en cuando los modifican y dejan de funcionar cosas.

Si tengo que recomendar algo quizá sería utilizar el framework de JavaScript llamado Knockout. Es muy bueno y se complementa bien con jQuery (se pueden usar en paralelo). Además Microsoft parece que lo apoya también y en las betas de Visual Studio 11 viene incluido por defecto en los proyectos. Entre otras muchas cosas lo más importante son las plantillas enlazadas a datos muy potentes, sencillas y estables.

Knockout

Espero que a más gente le pueda servir de orientación este post.