Compartir a través de


Tecnología de vanguardia

Creación de vistas móviles optimizadas en ASP.NET MVC 4

Dino Esposito

Dino EspositoSi se ve más allá de las consideraciones de sentido común sobre la programación de sitios móviles, descubrirá una contradicción inherente. Por un lado, hay gente que afirma poseer (o ser proclive a tener) un enfoque "mobile-first" (la versión móvil primero) con relación a la programación de aplicaciones y sitios. Por otro lado, se escucha a las mismas personas alabar las consultas de medios de CSS y los diseños líquidos. La contradicción que veo es que el uso común que se le da a las consultas de medios de CSS y a los diseños líquidos no antepone la perspectiva móvil, es decir, no es una técnica "mobile-first". En este artículo explicaré cómo usar la lógica del lado del servidor a fin de ofrecer la mejor visualización para un dispositivo determinado, incorporando una nueva característica de ASP.NET MVC 4 denominada modos de presentación.

El problema no son las consultas de medios de CSS como una tecnología. Es más, el problema tampoco es el diseño web con capacidad de respuesta (RWD) como la metodología subyacente de las consultas de medios de CSS, por no decir la filosofía que inspira esta tecnología. Entonces, ¿qué hace que el uso de las consultas de medios de CSS y los diseños líquidos sean un enfoque "mobile-last" (la versión móvil al final)? Podemos encontrar una pista en la frase usada para impulsar este enfoque: un código base único puede servir para múltiples vistas. En esta perspectiva, se usa CSS (una tecnología del lado del cliente) para alternar entre las vistas y se usa JavaScript para adaptar las vistas aún más, cuando CSS no es suficiente.

En mi opinión, en este enfoque existe la proposición subyacente de entregarles a todos los dispositivos el mismo contenido, donde solo se adapta el diseño de página para que se ajuste al tamaño de la pantalla. Al hacer esto, tal vez no se logre ofrecer la mejor experiencia posible a los usuarios. Soy partidario de que se debería tener un código base único (una base común de API web), pero al mismo tiempo es necesario enfocarse en casos de uso específicos para cada clase de dispositivo que se pretende abarcar. El término "móvil" tiene poco sentido hoy en día, ya que se está reemplazando por clases de dispositivos como smartphones, tabletas, computadoras portátiles y televisores inteligentes, sin mencionar los dispositivos que se pueden "vestir", como los anteojos con pantalla y los relojes de pulsera inteligentes.

Hace aproximadamente un año, presenté en esta columna un enfoque del lado del servidor para usarlo en el desarrollo de sitios con ASP.NET MVC: crear vistas ad hoc para cada clase de dispositivo compatible ("Desarrollo de sitios móviles: Marcado", msdn.microsoft.com/magazine/jj133814). Esto lo presenté en el contexto de ASP.NET MVC 3. Ahora bien, ASP.NET MVC 4 posee los modos de presentación antes mencionados, los que se pueden usar fácilmente para implementar una lógica del lado del servidor que de manera inteligente proporciona la mejor vista y el mejor contenido para un dispositivo dado. Para que sea realmente eficaz, este enfoque requiere que uno sepa la mayor cantidad de información posible sobre las capacidades del dispositivo objetivo. Sin embargo, además de la información básica sobre el tamaño de la pantalla y la orientación actual, el cliente no puede detectar mucho más. Es necesario recurrir a un repositorio de servidor con información del dispositivo.

Los modos de presentación en ASP.NET MVC 4

Antes de entrar de lleno en los modos de presentación, tengo que aclarar que este artículo (al igual que la tecnología misma del modo de presentación) se centra básicamente en la creación de un sitio nuevo y único que une de forma dinámica la misma URL con diferentes vistas. Si usted ya cuenta con un sitio web y desea proporcionar un sitio complementario optimizado para algunos dispositivos (móviles), eso representa un escenario diferente. Aún puede usar esta columna como guía para crear el sitio complementario, pero unificar varias URL con un sitio principal existente requiere herramientas diferentes.

En ASP.NET MVC 4, los modos de presentación son una característica del sistema que expande el comportamiento clásico de los motores de visualización con la capacidad de elegir el archivo de vista que resulta más adecuado para el dispositivo objetivo. En el artículo antes mencionado de ASP.NET MVC 3, usé un motor de visualización personalizado para este propósito. En esa solución, también me limité a las vistas de Razor. Con los modos de presentación, los métodos del controlador todavía invocarán, digamos, una vista llamada Index, pero el tiempo de ejecución de ASP.NET MVC elegirá un archivo de vista llamado index.mobile.cshtml si se sabe que el dispositivo objetivo es un dispositivo móvil.

Esto es una muy buena noticia, ya que significa que aún puede tener un código base único para su sitio. Simplemente necesita agregar archivos de vista CSHTML adicionales para cada clase de dispositivo que desea que sea compatible. Para comenzar a experimentar con los modos de presentación, veamos el código de ejemplo en la Figura 1.

Figura 1. La lista estándar de modos de presentación compatibles

<h2>
  Display Modes currently active
  (@DisplayModeProvider.Instance.Modes.Count mode(s))
</h2>
<ul>
@{
  foreach(var d in DisplayModeProvider.Instance.Modes)
  {
    <li>@(String.IsNullOrEmpty(d.DisplayModeId)
      ?"default" :d.DisplayModeId)</li>
  }
}
</ul>

La página en el código de la Figura 1 muestra la lista estándar de modos de presentación compatibles. La Figura 2 muestra la salida generada por la página.

Default List of Display Modes
Figura 2. Lista predeterminada de modos de presentación

Los modos de presentación de ASP.NET MVC 4 siguen algunas convenciones. En especial, cada modo de presentación se asocia con una palabra clave. La palabra clave se usa para componer el nombre del archivo de vista correspondiente. El modo de presentación predeterminado se dirige a una cadena vacía. Como resultado, cualquier aplicación de ASP.NET MVC administra correctamente los siguientes archivos de vista sin que se deba intervenir en ellos: index.cshtml e index.mobile.cshtml.

Para ver una demostración, copie el archivo index.cshtml en un nuevo archivo llamado index.mobile.cshtml y agréguelo al proyecto. Para distinguir entre los dos archivos, agregue lo siguiente al archivo móvil:

<div style="border-bottom: solid 1px #000">Mobile view</div>

Si ejecuta la aplicación y la prueba con Internet Explorer u otro explorador de escritorio, no cambia nada. Intente presionar F12 para acceder a las herramientas para desarrolladores de Internet Explorer y establezca un agente de usuario (UA) móvil al seleccionar Herramientas | Cambiar cadena del agente de usuario, tal como se muestra en la Figura 3.

Forcing a Mobile User Agent into Internet Explorer for Testing Purposes
Figura 3. Forzar un agente de usuario móvil en Internet Explorer con el propósito de realizar pruebas

Ya configuré algunos UA móviles y para tabletas. Por ejemplo, puede usar lo siguiente, que identifica el explorador solicitante como un smartphone HTC Desire Android:

Mozilla/5.0 (Linux; U; Android 2.1; xx-xx; HTC Desire Build/ERE27)
AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2

La Figura 4 muestra qué se obtiene del sitio ASP.NET MVC 4. La página que se proporciona a partir del mismo par de métodos del controlador y de la acción es index.mobile.cshtml. Más importante aún, todo esto se llevó a cabo sin tener que realizar ningún cambio en el estilo de programación y sin tener que aprender ninguna nueva habilidad.

Switching to a Mobile View
Figura 4. Cambiar a una vista móvil

Ir más allá de lo básico

Lo que hemos analizado hasta ahora es lo mínimo de lo que puede (y debe) hacer durante el desarrollo de un sitio móvil. Para transformar los modos de presentación en una solución para un sitio realista, se deben abordar dos puntos. El primero consiste en explorar las formas en las que se pueden agregar múltiples modos de presentación. El segundo es explorar las formas necesarias para introducir cierta lógica ad hoc con el fin de detectar los dispositivos de manera más confiable.

La lógica integrada que ASP.NET MVC usa para detectar los dispositivos móviles no es demasiado confiable. Posiblemente funciona con la mayoría de los smartphones, pero presenta errores con teléfonos celulares más antiguos. Por ejemplo, considere el siguiente UA:

SAMSUNG-GT-S3370/S3370DDJD4 SHP/VPP/R5 Dolfin/1.5 Qtv/5.3
SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1 OPN-N

Este UA hace referencia a un teléfono heredado (bastante popular hace algunos años) que ejecuta un SO patentado y un explorador personalizado basado en WebKit. El teléfono no es compatible con la conectividad mediante Wi-Fi, pero sorprendentemente posee excelentes capacidades de representación de HTML. La pantalla es más pequeña que la mayoría de los smartphones, pero no es táctil. Con la compatibilidad básica del modo de presentación de ASP.NET MVC, este teléfono no se reconoce como dispositivo móvil y se le proporcionan las versiones completas de las páginas. Esto presenta dos inconvenientes. En primer lugar, los usuarios prácticamente no pueden ver el contenido porque se ajusta de muy mala forma a la pantalla. En segundo lugar, gran parte del contenido se descarga y debido a que el teléfono no es compatible con la conectividad mediante Wi-Fi, todo esto sucede posiblemente a través de una conexión 3G, lo que ciertamente resulta lento y posiblemente costoso para el usuario.

Cuando hago hincapié en este punto, algunas personas responden que sus sitios simplemente no son compatibles con este tipo de teléfonos heredados. Esto tiene mucho sentido, pero ¿no sería mucho mejor enviar un mensaje cortés al usuario en dicho caso, en vez de dejar que todo se salga de control? Para poder enviar un mensaje como "Lo sentimos, pero este sitio no se puede visualizar desde su dispositivo", sigue siendo necesario reconocer el dispositivo apropiadamente y comprender que no es un iPhone, por ejemplo. Además, la opción de omitir de manera segura los dispositivos heredados es una decisión comercial, no de implementación. No aceptar las generaciones más antiguas de dispositivos puede afectar sus negocios más allá de lo que pueda imaginar. De esta forma, veamos cómo agregar múltiples modos de presentación a un sitio, con el fin de proporcionarles contenido adecuadamente a varias clases de dispositivos.

Clases de dispositivos

Un sitio web moderno ofrece la mejor experiencia posible, sin importar el tipo de dispositivo. "La mejor experiencia posible" significa proporcionar casos de uso ad hoc, datos seleccionados y funciones específicas. El marcado resultante debe ser específico para el dispositivo. Si por el contrario se ajustan parámetros en el cliente (tal como sucede cuando se depende de las consultas de medios de CSS), realmente lo que se consigue es una visión unificada de páginas que luego se adaptan a pantallas más pequeñas. Esto significa, principalmente, ocultar algunos bloques, desplazar otros verticalmente y, tal vez, solicitar un conjunto más liviano de imágenes. La visión unificada de páginas suele ser la página de escritorio. Personalmente no llamaría a esto un enfoque mobile-first.

Al decir "tipo de dispositivo" no me refiero a la distinción entre un dispositivo iPhone y un dispositivo Windows Phone. Por el contrario, mi objetivo es usar la lógica que puede brindar un marcado diferente para smartphones, tabletas y equipos portátiles. Así, en ASP.NET MVC 4 tenemos, al menos, tres modos de presentación: smartphone, tableta y predeterminado (para exploradores de escritorio). Voy a agregar una nueva clase DisplayConfig que se invoque en App_Start (consulte la Figura 5).

Figura 5. Clase DisplayConfig

public class DisplayConfig
{
  public static void RegisterDisplayModes(IList<IDisplayMode> displayModes)
  {
    var modeDesktop = new DefaultDisplayMode("")
   {
     ContextCondition = (c => c.Request.IsDesktop())
   };
   var modeSmartphone = new DefaultDisplayMode("smart")
   {
     ContextCondition = (c => c.Request.IsSmartphone())
   };
   var modeTablet = new DefaultDisplayMode("tablet")
   {
     ContextCondition = (c => c.Request.IsTablet())
   };
   displayModes.Clear();
   displayModes.Add(modeSmartphone);
   displayModes.Add(modeTablet);
   displayModes.Add(modeDesktop);
 }
}

La primera clase vacía la colección de modos de presentación proporcionada. De esta forma, se deshace de los modos predeterminados. A continuación, el código completa la colección del sistema proporcionado con una nueva lista de modos de presentación. Un nuevo modo de presentación es una instancia de la clase DefaultDisplayMode. El nombre del modo se establece mediante el constructor. La lógica que determina si consigue una coincidencia con un agente de usuario se establece a través de la propiedad ContextCondition.

La propiedad ContextCondition es un delegado que acepta un objeto HttpContextBase y devuelve uno booleano. El cuerpo del delegado consiste en sumergirse en el contexto HTTP de la solicitud actual con el fin de determinar si un modo de presentación dado es adecuado o no. En la Figura 5, uso algunos métodos de extensión para mantener el código altamente legible. La Figura 6 enumera dichos métodos de extensión.

Figura 6. Métodos de extensión para mantener el código legible

public static class HttpRequestBaseExtensions
{
  public static Boolean IsDesktop(this HttpRequestBase request)
  {
    return true;
  }
  public static Boolean IsSmartphone(this HttpRequestBase request)
  {
    return IsSmartPhoneInternal(request.UserAgent);
  }
  public static Boolean IsTablet(this HttpRequestBase request)
  {
    return IsTabletInternal(request.UserAgent);
  }
  // More code here.
}

Todo el código analizado hasta ahora no es más que pura infraestructura. Finalmente se obtiene un método de escritura para cada modo de presentación. Cada método toma un agente de usuario y debe devolver una respuesta booleana. A continuación se muestra una rutina muy básica para comprobar tabletas:

private static Boolean IsTabletInternal(String userAgent)
{
  var ua = userAgent.ToLower();
  return ua.Contains("ipad") || ua.Contains("gt-");
}

Esta rutina solo garantiza la correcta detección de dispositivos iPad y Galaxy Tab, pero permite comprender cómo se deben escribir estas rutinas de condición de contexto. Recomiendo agregar más código para comprobar, por lo menos, la presencia de smartphones. Para detectar tabletas y smartphones, se puede aprovechar cualquier Repositorio de descripciones de dispositivos (DDR) de código abierto o comerciales. Trataré este tema con más detalle en mi próxima columna.

Negocios serios

No siempre será necesario adoptar un enfoque del lado del servidor para sitios móviles, pero sí resulta un tema serio cuando existen negocios detrás del sitio. No recomendaría un enfoque del lado del servidor para el sitio de una conferencia o cualquier tipo de sitio de corta vida, por ejemplo. Sin embargo, un sitio comercial cuyo objetivo consiste en llegar al mayor público posible tiene que poner énfasis en la optimización para dispositivos más allá de una simple representación móvil.

En el cliente, se está limitado al tamaño y la orientación de la ventana del explorador y no se puede comprobar cuál es el SO o si posee capacidades táctiles, o comprobar cosas más avanzadas como si el dispositivo es compatible con redes inalámbricas, transmisiones, imágenes en línea, SMS y más. Los modos de presentación facilitan especialmente la implementación de un enfoque de múltiples vistas en ASP.NET MVC 4.

En mi siguiente columna, voy a completar mi argumento al mostrar cómo integrar el DDR que usa Facebook (Wireless Universal Resource File (WURFL)) con ASP.NET MVC 4.

Dino Esposito es autor de “Architecting Mobile Solutions for the Enterprise” (Microsoft Press, 2012) y “Programming Microsoft ASP.NET MVC 3” (Microsoft Press, 2011) y coautor de “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2008). Con residencia en Italia, Esposito participa habitualmente en conferencias y eventos del sector en todo el mundo. Puede seguir a Dino por Twitter en twitter.com/despos.

Gracias al siguiente experto técnico por su ayuda en la revisión de este artículo: Mani Subramanian (Microsoft)
Mani Subramanian ha participado en el desarrollo y la realización de pruebas de proyectos de software durante los últimos 12 años, con un enfoque en SOA, informática en nube y core.net.