martes, 7 de enero de 2014

SignalR 2.0 en MVC - Ejemplo práctico Horse Race

El post anterior jugamos con el protocolo WebSockets y vimos como realizar un ejemplo en un proyecto ASP .NET MVC. Hoy adaptaremos el mismo ejemplo de la carrera de caballos usando SignalR 2.0.

SignalR en su versión 2.0 es un librería que aporta funcionalidades para gestionar conexiones bidireccionales entre cliente y servidor, en realidad no se puede decir que sea una alternativa a WebSockets sino más bien una librería que facilita este tipo de comunicación en entornos MS. Me explico, si recordamos las limitaciones de WebSockets, no siempre los navegadores aceptan este tipo de protocolo a nivel de transporte. Una de las ventajas que veo en SignalR es que nos aleja un poco del nivel de transporte y se encarga de determinar automáticamente que protocolo se usará en función de las características del cliente que accede a nuestra aplicación web.

En el post anterior, teníamos los siguientes elementos:
  • Controlador estandar para gestionar la vista principal donde se muestra la carrera
  • Vista con un canvas y 2 caballos
  • Script para gestionar la conexión WebSocket en cliente
  • Controlador "webApi" para gestionar la conexión WebSockets en servidor
  • Clase de negocio que gestiona la carrera en servidor

Podríamos partir del mismo proyecto web anterior o crear uno nuevo, lo único que cambiaremos es el script que teníamos en cliente para gestionar la conexión WebSockets y el controlador WebApi que gestiona la conexión WebSocket en server.

Para continuar con el ejemplo es necesario instalar el paquete de SignalR desde Visual Studio (2013) usando el siguiente comando desde la consola del administrador de paquetes de VS -> install-package Microsoft.AspNet.SignalR. Una vez ejecutado este comando si vamos a la carpeta Scripts del proyecto veremos que se han añadido las librerías jquery.signalR-2.0.1.js y jquery.signalR-2.0.1.min.js (la versión podría variar).

Vamos a crear el Hub en servidor. Crearemos una carpeta Hubs en nuestro proyecto, hacemos click botón derecho y seleccionamos "Agregar nuevo elemento" en el menú contextual. Veremos que nos aparece una opción SignalR entre las plantillas, nos situamos en el y seleccionamos tipo de archivo Clase de concentrador SignalR (v.2).
namespace HorseRace.SignalR.Hubs
{
  public class MyHorseRaceHub : Hub
  {
    public void init()
    {
      Race BusinessHorseRace = new Race();
      Task tRace = BusinessHorseRace.InitHorseRace();
      while (!tRace.IsCompleted)
      {
        Thread.Sleep(50);
        List<int> positions = BusinessHorseRace.GetMovement();
        Clients.Caller.message(System.Web.Helpers.Json.Encode(positions));
      }
    }
  }
}
Como veis el código en servidor se simplifica bastante usando SignalR. El siguiente paso es iniciar el Hub que acabamos de crear cuando arranque el site. Si estamos trabajando con MVC 5.0 y Visual Studio 2013 automáticamente al crear el proyecto se añade una clase en la root StartUp donde añadiremos código para mappear e configurar nuestros hubs. En caso de no estar usando la versión 2013 de Visual Studio os tendréis que crear una clase plana vosotros mismos con el siguiente código y asegurarse que se llama desde global.asax al iniciar la aplicación.
[assembly: OwinStartupAttribute(typeof(HorseRide.SignalR.Startup))]
namespace HorseRace.SignalR
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}
Vamos con la parte cliente. Como comentábamos al principio del post sólo tendríamos que cambiar el script de conexión al websocket por el siguiente script:
    $(function () {
        var conexion = $.connection.myHorseRaceHub;

        conexion.client.message = function (message) {
            var positions = $.parseJSON(message);
            initField();
            drawHorseBlanco(positions[0], yC1);
            drawHorseNegro(positions[1], yC2);
        };

        $.connection.hub.start().done(function () {
            $('#btnConnect').click(function () {
                conexion.server.init();
            });
        });
    });
Si pulsamos "Iniciar Carrera" ya tendríamos los caballos compitiendo de nuevo.

Con SignalR podríamos realizar un broadcast desde servidor a todos los clientes conectados de manera bastante sencilla.
En cliente sería añadir el siguiente código:
   conexion.client.broadcastMessage = function (message) {
      alert(message);
  };
En server, añadiría este código al inicio del método init que hemos creado en el Hub:
   Clients.All.broadcastMessage("nuevo cliente conectado");
Esto que nos ha costado 2 líneas de código con SignalR en el ejemplo anterior trabajando directamente con WebSockets se podría haber hecho pero nos hubiese dado más trabajo.

Hasta aquí el artículo de hoy, si alguien estuviese interesado en que le haga llegar el código que contacte conmigo vía linkedin o google. Recordaros, como siempre, que podéis seguir areaTIC en las redes sociales y comentar todo lo que creáis oportuno! Hasta la próxima!!

No hay comentarios:

Publicar un comentario en la entrada