Introducción a SignalR y el clásico ejemplo de un chat

viernes, 6 de diciembre de 2013

Introducción

SignalR es un librería open source inicialmente creada por Damian Edwards y David Fowler y que ahora forma parte de la familia de Asp.Net. Mediante SignalR podemos añadir funcionalidad de tipo comunicación en tiempo real entre cliente y servidor, teniendo así una comunicación bidireccional.

Esta disponible mediante NuGet, esta muy integrado con proyectos Asp.net. En pocos pasos mediante su API se puede crear una aplicación web donde desde el lado del servidor se puede invocar funciones declaradas en un cliente javascript en el navegador.



SignalR no solo puede ser utilizado en un entorno servidor Asp.Net y su cliente en javascript, hay otros entornos donde puede ser desarrollado. Mediante OWIN ( Open Web Interface for .NET) se puede crear un servidor self host con cualquier código .NET, desde un servicio windows hasta un proyecto de consola. También se pueden crear clientes con proyectos de la tienda de windows, windows phone, WPF, Silverlight por ejemplo.
En SignalR hay dos apis para la comunicación entre cliente y servidor:
  • Comunicación persistente: Api de bajo nivel que permite manejar eventos como connected  y disconnected. 
  • Hubs: Api de alto nivel, de uso más sencillo y donde parece magia la comunicación entre el servidor y cliente.
La primera opción de transporte en SignalR es WebSocket si es posible, sino ira probando métodos de transporte más antiguos. La mejor opción de transporte es WebSocket porque realiza una mejor gestión de memoria en servidor y es el único método donde existe una conexión persistente real entre cliente y servidor, las demás opciones lo simulan pero no es real.

Lo bueno es que todo esto lo gestiona SignalR y es transparente para el desarrollador, lo que convierte a SignalR en muy sencillo de utilizar.

El ejemplo más visto con SignalR es un chat, así que no voy a ser menos y vamos a hacer este ejemplo, en futuros post veremos más ejemplos con SignalR.

Ejemplo de un chat

Para el ejemplo de un chat vamos a utilizar Hubs, que crearemos en el proyecto web. Empecemos:

Creamos un proyecto MVC


Ahora mediante NuGet añadimos SignalR, el paquete completo para servidor, donde se incluyen las librerias para levantar el servidor y también la librería para el cliente javascript.



Añadimos una clase Startup, que sera invocada por el motor de SignalR al arrancar la web y que se encarga de mapear las clases hub que hay en la solución y generar dinámicamente el script que se encontrará en /signalR/hubs, que hará de proxie del servidor para el cliente.
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
    }
}

Añadimos la clase ChatHub que sera la clase con la que el cliente tendrá comunicación bidireccional.


public class ChatHub : Hub
{
    public void SendMessage(string userName, string message)
    {
        Clients.All.addMessage();
    }
}

La clase Hub tiene un método SendMessage que sera invocado por un cliente javascript, y esta a su vez invoca la función addMessage de todos los clientes conectados. Fijaros que por convención comienza con minúscula el nombre de la función en javascript siguiendo lower camel case.

creamos el controller, con la función Index que nos devuelve la vista.

public class ChatController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

Modificamos la configuración de la clase RouteConfig que se ha creado por defecto para que el controller por defecto sea ChatController.
public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Chat", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Y finalmente creamos la vista, tenemos la parte html
@{
    ViewBag.Title = "Index";
}

SignalR Chat Example

Messages

y la parte javascript donde reside el código cliente que se comunica con el Hub en servidor.
@section scripts {
    
    
    
}

Donde tenemos la referencia a la libreria javascript de SignalR y al directorio ~/signalr/hubs que genera el motor de SignalR de forma dinámica y donde estará el proxy de nuestro ChatHub. Nos creamos una instancia del proxy y la función que será invocada desde servidor para añadir un nuevo mensaje de un cliente, después se comienza la conexión con el servidor. En la función send se realiza una llamada al método definido en servidor para comunicar un nuevo mensaje y este a su vez invocara la función addMessage de todos los clientes conectados, incluido el mismo cliente que lanza el mensaje inicial.
Fijaros que tanto el hub como la funcion de servidor cuando se utliza desde javascript por convención se utiliza lower camel case.

Con esto hemos terminado el chat de ejemplo


Libros Relacionados

Introducción a ASP.NET SignalR es de Jose M. Aguilar.
Signalr: Realtime Application Development

Pro ASP.Net Signalr: Real-Time Communication in .Net with Signalr 2.0

SignalR Programming in Microsoft ASP.NET

6 comentarios:

  1. De los libros que mencionas, el primero de Jose M. Aguilar el enlace en inglés dice que no está disponible porque están trabajando en una nueva versión.

    El otro Pro ASP.NET SignalR aún no está en venta. Con suerte en el sitio web del publicador haya una versión previa.

    El último libro que mencionas es también de Aguilar y no está a la venta hasta el 22 de febrero del 2014.

    El único libro disponible lo he leído Signalr: Realtime Application Development pero habla de la version 1.x no la versión 2.0 de Signalr y desafortunadamente los ejemplos no corren sin hacer algunos cambios.

    ResponderEliminar
    Respuestas
    1. Sabia que algunos libros no estaban disponibles por el momento.

      Gracias por el aporte.

      Eliminar
  2. Gran blog !!.
    Viendo el artículo y comentarios me parece muy potente.
    Los ejemplos que he visto la mayoría es el típico chat.
    Me gustaría ver algún ejemplo más real y empresarial, por ejemplo:

    una aplicación Windows Forms que haga de Server y de Client

    una aplicación Windows Forms que haga Client y un Servicio Windows o Aplicación de Consola que haga de Server.

    Sé que muchos desarrolladores en la comunidad aportan en github o codeplex, o codeproject igual existe un ejemplo completo de estas características.

    Gracias.

    SignalR y los ejemplos de Chat.

    JM Aguilar:

    Y voy a aprovechar para comentar algo que me preguntan muy a menudo: por qué hay tantos ejemplos de chat en SignalR.

    Es cierto que la mayoría de ejemplos son un chat, pero, desde mi punto de vista, tiene una explicación lógica: no distrae del objetivo del post.

    Normalmente, el objetivo de este tipo de artículos es mostrar el funcionamiento de SignalR, y éste es el mismo para todo tipo de aplicaciones. Al usar un chat, no es necesario dar explicaciones sobre lo que se pretende construir porque todos sabemos lo que es, por lo que permite focalizar el contenido del artículo. Y la base tecnológica de un chat es exactamente la misma que la de otro tipo de sistemas realtime, por lo que así podemos cubrir el objetivo.

    Incluso el uso de Signalr desde otro tipo de aplicaciones (como el ejemplo de Winforms como cliente o servidor que comentas), también podría demostrarse sobre un chat, pues el foco de un artículo de ese tipo podría ser el uso del self-hosting (necesario para hacer que ese tipo de aplicaciones puedan actuar como servidores Signalr) o el cliente .NET (necesario para que ese tipo de aplicaciones actúen como clientes SignalR).

    En definitiva: si encuentras ejemplos de un chat, no hay que mirarlo como un bloque de código para usar directamente en tus aplicaciones. Hay que usar ese ejemplo simple para entender el uso y extrapolarlo para otros escenarios y aplicaciones. Dado que no es necesario entender lo que pretendemos hacer (un chat) debido a su simpleza, tendremos más fácil centrarnos en lo realmente importante, el uso de SignalR.

    Aún así sería interesante otro ejemplo más empresarial. Seguro en github algún gurú ha compartido algo realmente interesante.

    ResponderEliminar
  3. Hola muchas gracias por el comentario.

    Es cierto que hay muchos ejemplos de SignalR por su sencillez de comprensión.

    Te dejo un enlace de otro artículo sobre SignalR donde explico un ejemplo de crear un Logger mediente WPF de una aplicación Web.

    http://xurxodeveloper.blogspot.com.es/2013/12/logger-wpf-en-tiempo-real-de-una-web.html

    Saludos

    ResponderEliminar
  4. Muy buena explicacion, habra un articulo donde se vea un ejemplo de mensajes pero para un usuario en especifico y no a todos. (Ejemplo de Clients.User en vez de Clients.All)

    ResponderEliminar
  5. Saludos Jorge, tomando en cuenta lo que comentas acerca del por qué hay sólo ejemplos de chat con la librería de SignalR, entonces se puede partir de dichos ejemplos para hacer una aplicación del tipo video llamada? tanto cliente como servidor.
    En mi caso, tengo el ejemplo de chat utilizando como cliente dispositivos Android, ahora quisiera incorporar a los mismos la parte de video llamada.
    A la espera de tus comentarios, y muchas gracias por tu aporte al respecto.

    ResponderEliminar