[Windows Phone] ASP.net SignalR, mundo de posibilidades!

SignalRIntroducción

La evolución en el mundo de las Aplicaciones es constante y rápido y los usuarios cada vez requieren funcionalidades más exigentes. Muchas de las Applicaciones destacadas en la tienda hacen un correcto uso de respuesta inmediata, famosos chats, famosos juegos donde los usuarios dibujan en tiempo real, finanzas, etc. ¿Como realizar este tipo de Aplicaciones?. Si estas interesado sigue leyendo porque en este artículo aprenderemos como crear Aplicaciones en tiempo real para Windows Phone utilizando SignalR.

¿SignalR?

SignalR es una biblioteca Open Source (disponible en GitHub) perteneciente a la familia ASP.NET destinada a la creación de aplicaciones que respondan en tiempo real. Si alguna vez habéis trabajado con conexiones persistentes conceptos como «Long Polling» o «Web Sockets» os serán familiares. Estos conceptos se utilizan en conexiones persistentes que permiten una interacción continua por parte de clientes con el servidor. No entraremos a analizar los problemas concecuentes en los conceptos anteriores ya que no es el objetivo del artículo, lo que si vamos a destacar es que SignalR nos añade una capa de abstracción que negocia automáticamente los transportes a autilizar e irá haciendo «fallback» hasta encontrar una capa que se pueda usar. Automáticamente verificará si se soporta «Web Sockets», en caso contrario utilizará «Server Sent Events», y asi hasta llegar al «Long Polling» como última alternativa.

NOTA: En este artículo utilizaremos la versión 2.0 para crear nuestras Aplicaciones. Si queréis ver que cambios hay entre SignalR 1.x y la versión 2.0 podéis echarle un vistazo al siguiente enlace.

Manos a la obra!

Vamos a comenzar creando una simple web que utilizará el cliente jQuery de SignalR donde los usuarios conectados entrarán a un chat donde poder comunicarse entre ellos.

Para ello:

  1. Crearemos un proyecto web.
  2. Añadiremos las librerías de SignalR haciendo uso de NuGet.
  3. Crearemos una clase OWIN para ayudarnos a configurar el arranque de la Aplicación.
  4. Usaremos las librería jQuery de SignalR en la web para enviar mensajes y mostrar los mensajes recibidos desde el Hub.

Comenzamos por el primer paso, vamos a crear un proyecto Visual Studio utilizando la plantilla «ASP.NET Empty Web Application»:

ASP.NET Empty Web Application

ASP.NET Empty Web Application

Procedemos a instalar las librerías de SignalR. Para ello utilizaremos NuGet y tenemos dos opciones:

  • Opción A: Hacemos clic drecho sobre las referencias del proyecto, elegimos gestionar paquetes NuGet, buscamos SignalR y elegimos el paquete deseado pulsando instalar:
Manage NuGet Packages

Manage NuGet Packages

SignalR

SignalR

  • Opción B: Abrimos la consola de NuGet, Package Manager Console (Tools | Library Package Manager | Package Manager Console) y ejecutamos el siguiente comando:
install-package Microsoft.AspNet.SignalR

Tras la instalación podemos comprobar que contamos con nuevas referencias en el proyecto además de nuevos scripts dentro de la carpeta Scripts.

Añadimos una nueva clase a nuestro proyecto, la llamaremos ChatHub:

public class ChatHub : Hub
{
     public void EnviarMensaje(string mensaje)
     {
          Clients.All.Enviar(mensaje);
     }
}

Analicemos que hemos incluido en esas cortas líneas. De entrada, la clase deriva de la clase Microsoft.AspNet.SignalR.Hub. La clase Hub nos aporta un RPC de alto nivel sobre una conexión persistente. Microsoft.AspNet.SignalR.Hub.Clients es un objetivo de tipo dynamic que utilizaremos para relacionar la parte del cliente con la del servidor. La clase basicamente permite a la parte cliente, por ejemplo desde jQuery, acceder a sus métodos.

Por lo tanto:

  • Declaramos métodos públicos en el hub para que desde la parte cliente se pueda acceder a ellos.
  • Usamos un objetivo dynamic llamado Clients para acceder a los clientes conectados al Hub.
  • Llamamos a una función en el cliente para actualizar la información (en nuestro ejemplo esa función es Enviar).

Continuamos, añadimos otra clase llamada Startup:

public class Startup
{
     public void Configuration(IAppBuilder app)
     {
          // Any connection or hub wire up and configuration should go here
          app.MapSignalR();
     }
}

Añadimos la página HTML (Add | HTML Page). En el código añadido añadiremos el código necesario para crear el chat. De entrada en el Header dela página incluiremos los scripts necesarios:

<script src="Scripts/jquery-1.6.4.min.js"></script>
<script src="/Scripts/jquery.signalR-2.0.0.min.js"></script>
<script src="/signalr/hubs"></script>

Dentro del Body añadimos:

<h1>SignalR Chat </h1>
<p>
<label for="Mensaje">Mensaje:</label>
<input type="text" id="Mensaje" />
</p>
<p>
<input type="button" id="Enviar" value="Enviar Mensaje" />
</p>
<ul id="Mensajes">

Simple. Una caja de texto donde permitir al usuario escribir su mensaje, un botón para enviarlo y un listado donde ir mostrando todos los mensajes. Por último, añadimos el siguiente script:

<script type="text/javascript">
$(function () {
var chat = $.connection.chatHub;
chat.client.enviar = function (mensaje) {
$('#Mensajes').append('<li>' + mensaje + '</li>');
};
$.connection.hub.start().done(function () {
$("#Enviar").click(function () {
chat.server.enviarMensaje($('#Mensaje').val());
$('#Mensaje').val("");
});
});
});
</script>

Analicemos detenidamente el código añadido en el script. El objetivo del mismo es comunicarse con el Hub creado. Creamos un proxy del hub utilizando:

$.connection.yourHubClass

E inicializamos el hub usando:

$.connection.hub.start()

Listo!. Pulsamos F5 y ejecutamos el proyecto en modo debug en el navegador. Copiamos la URL y abrimos más instancias del navegador u otros navegadores. Para probar el resultado bastará con enviar mensajes desde cada navegador y ver como el resultado aparece en cada uno de ellos. Impresionante, ¿cierto?

El resultado

El resultado

La Aplicación Windows Phone

Ya hemos visto la potencia de SignalR y posiblemente a estas alturas muchas ideas estarán rondando vuestra cabeza. Sería fantástico poder utilizar la tecnología en Aplicaciones móviles…

Se puede!. Hay librerías para trabajar con SignalR para:

  • jQuery (ya la hemos probado)
  • .NET 4.0/4.5
  • Silverlight 5
  • Windows Store Apps
  • Windows Phone
  • Portable Class Library
  • MonoTouch
  • MonoDroid

Además el equipo de SignalR se encuentra trabajando para que en un futuro se tenga también librerías para:

  • IOS (nativa)
  • Java
  • C++

Vamos a crear una aplicación Windows Phone donde utilizaremos las librerías SignalR para Windows Phone y analizar todas las posibilidades:

Windows Phone Application

En este ejemplo para simplificar al máximo el proceso y lograr concentrar toda la atención en SignalR vamos a seleccionar un proyecto de tipo Windows Phone Application.

Comenzamos añadiendo las librerías SignalR cliente para Windows Phone. Al igual que hicimos previamente con la parte web, utilizaremos NuGet para instalar las librerías:

SignalR Client

SignalR Client

Tras instalar las librerías vamos a comenzar a crear nuestra Aplicación Chat. Comenzamos por la interfaz:

<StackPanel Orientation="Vertical" VerticalAlignment="Bottom">
     <ScrollViewer Height="450">
          <TextBlock Name="chatDialog" Width="320" Padding="5"
          Foreground="{StaticResource PhoneAccentBrsh}" FontSize="36"/>
     </ScrollViewer>
     <StackPanel Orientation="Horizontal">
          <TextBox Name="chatTextbox" MaxLength="20" Width="350" HorizontalAlignment="Center"/>
          <Button Content="Enviar"/>
     </StackPanel>
</StackPanel>

Añadimos un texto (control TextBlock) donde iremos añadiendo los mensajes enviados y recibidos del chat además de por supuesto una caja de texto (control TextBox) donde escribir los mensajes y un botón para enviarlos.

IHubProxy _chat;
HubConnection _hubConnection;

En el evento OnNavigatedTo, evento que se ejecutará siempre que una página pasa a ser la página activa (se entra en la página) iniciamos el HubConnection con la ruta hacia nuestro servidor.  Una vez creado el Proxy Hub, usamos la síntaxis HubProxy.On<T> para registrar un evento del lado del cliente (que el servidor podrá llamar). En nuestro caso el evento será Message que añadirá a un TextBlock dela interfaz el mensaje recibido:

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
     base.OnNavigatedTo(e);

     // Conectamos con el servicio:
     _hubConnection = new HubConnection("http://localhost:12345/");

     // Creamos un proxy con el servicio chat:
     _chat = _hubConnection.CreateHubProxy("ChatHub");

     // Cuando recibamos un mensaje, los mostraremos:
     _chat.On<string>("Message", message => Deployment.Current.Dispatcher.BeginInvoke(() =>
     {
          chatDialog.Text += "\n" + message;
     }));

     // Inicio de la conexión:
     await _hubConnection.Start();
}

El clic de botón utilizará el Hub Proxy creado anteriormente para incovar métodos del servidor. El primer parámetro de la función Invoke es el nombre del método (en el servido)r y a continuación tenemos la lista de los parámetros aceptados por el servidor:

private async void sendChatBtn_Click(object sender, EventArgs e)
{
     // Envio de un mensaje al servidor:
     await _chat.Invoke("Send", chatTextbox.Text).ContinueWith(task =>
     {
          if (!task.IsFaulted && task.Exception == null)
          {
               Deployment.Current.Dispatcher.BeginInvoke(() => { chatTextbox.Text = string.Empty; });
          }
     });
}

Todo listo!. Pulsamos F5 y ejecutamos la aplicación en el emulador. Tras ejecutarse la aplicación y esperar unos leves segundos (tiempo que tardará el programa en llamar al servicio) y…

Error!. No podemos conectar con nuestro servicio.

Oops!, ¿que ocurre?

Ya sabemos porque. El emulador de Windows Phone 8 es una máquina virtual en Hyper-V y la red de la misma es distinta a la de la máquina de desarrollo.

Para resolver el problema causado por la dirección localhost debemos reconfigurar el servicio web e IIS Express para aceptar conexiones de otros dispositivos. Estos dispositivos conectarán con el servicio utilizando la IP de la máquina de desarrollo.

Ya hemos mencionado que vamos a utilizar la IP de la máquina de desarrollo. Abre el símbolo del sistema en la máquina de desarrollo y escribe:

ipconfig

Esta línea de comando nos facilitará la dirección IP de la máquina. Vamos a modificar el archivo de configuración de IIS Express que lo podéis encontrar en la ruta:

%USERPROFILE%\<your user name>\Documents\IISExpress\config\

El nombre del fichero es applicationhost.config. Lo abrimos y buscamos la sección <sites>. Buscamos el sitio que tenga el nombre de nuestro servicio y nos fijamos en el apartado <bindings>.

Tenemos un binding ya establecido a localhost que no podemos eliminar. Por lo tanto, añadimos un segundo binding igual al ya creado reemplazando localhost por la IP de la máquina de desarrollo. Añadimos también en el Firewall de Windows una excepción para IIS Express en el puerto que estámos utilizando.

Guardamos los cambios. Cerramos Visual Studio y lo volvemos a ejecutar con privilegios de Administrador (es necesario para registrar nuestra aplicación con un servicio no alojado en localhost). Ejecutamos la aplicación.

Todo listo. Pulsa F5 para ejecutar la aplicación en el emulador. El emulador arrancará y si probramos el chat… mágico!

El resultado

Llegado a este punto lo tenemos todo listo. Podéis ver el resultado a continuación:

Podéis descargar el ejemplo desde el siguiente enlace:

NOTA: En la descarga tambien tenéis disponible la Aplicación Windows 8 del chat.

Conclusiones

Hemos aprendido las posibilidades que nos brinda SignalR, framework destinado a la creación de Aplicaciones en tiempo real. Hemos sido capaces de configurar SignalR en un Host OWIN  creando un cliente sencillo HTML + JavaScript. A continuación hemos creado una Aplicación Windows Phone 8 utilizando C # + XAML que puede comunicarse con nuestro servidor SignalR.

Más información