Chalalo Land

Tecnologías ASP.NET y un poco Más

Contacto


 Si quierer cooperar, yo feliz, muy agradecido :)

De donde me Visitan?

Locations of visitors to this page

Generic Content

Si te gustaron los articulos, y te animas te estaría muy agradecido!


Recent Posts

Tags

Community

Blogs de MVP

Amigos Geeks

Blogs Imperdibles

GODS

Archives

Email Notifications

[Tutorial] Comenzando con SignalR y Razor View

Hola!!, estuve un poco ausente de blog por temas de vacaciones , jejee, todos necesitamos un descanso, pero ya estamos de vuelta , esta vez quiero mostrar un ejemplo de SignalR  utilizando las características de Razor engine.

Primero que nada, te recomiendo ver los siguientes artículos sobre SignalR, me fueron de gran ayuda para comprender los fundamentos de SignalR

Paso siguiente de haber leído los artículos veamos como realizar una implementación , con lo denominado “Conexiones Persistentes” (si no conoces el término, revisa el primer artículo).

La idea del proyecto a realizar es un backend (server) que va a enviar mensajes a distintos clientes, el server debe poder ver cuando se conecta y desconectan los clientes:

image

Vamos a comenzar entonces con la creación de un proyecto de ASP.NET Web API, luego vamos a obtener los archivos necesarios desde el NuGET, recuerda seleccionar la opción “Incluir versión previa” ya que este paquete, a la hora de escribir este artículo se encuentra en RC. Luego buscas signalR y elijes “Microsoft ASP.NET SignalR”

image

Como voy a usar serialización JSON y quiero compatibilidad con versiones de IE más antiguas, voy a agregar la librería JSON2

image

Una vez con esto instalado, voy a crear una carpeta Mensaje en donde voy a tener el objeto mensaje, que será pasado entre el cliente y el servidor, además la clase MensajeConn que implementa la comunicación.

El mensaje es bastante sencillo, solo consta de un titulo y un texto, justo lo necesario para el ejemplo Sonrisa

Estructura de la solución

Clase Mensaje

image

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

 

namespace SignalDemo1.Mensaje

{

    public class Mensaje

    {

 

     public string Titulo {get;set;}

     public string Texto{get;set;}

 

    public Mensaje(string titulo,string texto){

          this.Titulo = titulo;

          this.Texto = texto;

        }

 

        public Mensaje()

        {

 

        }

    }

}

Ahora veamos la clase MensajeConn:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using Microsoft.AspNet.SignalR;

using System.Threading.Tasks;

using Newtonsoft.Json;

 

namespace SignalDemo1.Mensaje

{

    public class MensajeConn : PersistentConnection

    {

      

        protected override Task OnConnected(IRequest request,
                                          
string
connectionId)

        {

          Mensaje mensaje = new Mensaje("Servidor", "Nueva Conección " +
                                                         connectionId);

          return Connection.Broadcast(mensaje);

        }

 

        protected override Task OnReceived(IRequest request,
                                      
string connectionId, string
data)

        {

            Mensaje mensaje = JsonConvert.DeserializeObject<Mensaje>(data);

            return Connection.Broadcast(mensaje);

        }

 

        protected override Task OnDisconnected(IRequest request,
                                                     
string
connectionId)

        {

            Mensaje mensaje = new Mensaje("Servidor", "Desconectado " +
                                                            connectionId);

            return Connection.Broadcast(mensaje);

        }

    }

}

Importante es notar esta clase hereda de la clase abstracta PersistentConnection que nos brindará la posibilidad de sobrescribir los métodos para la interacción de mensajes.

Es necesario revisar la documentación oficial de SignalR para que veas las posibilidades de sobre escritura de métodos y el uso que podemos darle, revisa el siguiente link:

https://github.com/SignalR/SignalR/wiki/PersistentConnection

En mi caso, solo quiero ejecutar acciones cuando un cliente se conecta, cuando se desconecta y cuando se envía un mensaje hacia los clientes).

Para la conexión y desconexión simplemente envió un mensaje simple junto al connectionId, el cual identifica únicamente la conexión (luego con esto podemos enviar mensajes a clientes en particular)

El método OnReceived permitirá recibir un objeto serializado con JSON y enviar con el método Broadcast a todos los host conectados.

Paso siguiente, y no olvidar, ya que si no, no va a funcionar la conexión (error 404 al momento de tratar de conectarse el cliente js hacia el servidor) es definir en el global.asax la definición del endpoint:

RouteTable.Routes.MapConnection<Mensaje.MensajeConn>("mensaje", "/mensaje");

 

Un poco de Razor View, Blundes y esas hiervas.

Ya definimos el funcionamiento deseado para la comunicación, ahora veamos algunas cosillas que nos simplificarán la vida en las vistas.

Para la implentación en el cliente debemos agregar dos archivos JS que fueron agregados al proyecto por nuget, ahora con la posibilidad en asp.net 4.5 de hacer bundle (unir,combinar) script para disminuir las llamadas al server, vamos a definir en nuestro archivo blundleConfig:

bundles.Add(new ScriptBundle("~/bundles/jquerysignalr").Include(

                              "~/Scripts/json2.js",

                    "~/Scripts/jquery.signalR-{version}-rc2.js"));

Con esto unimos en un solo archivo que se llamará jquerysignalr, los archivos json2 y jquery.signalR-1.0.0-rc2.

Si quieres saber más sobre el tema de combinación y minificación de scripts y css revisa:

http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

Interfaz de Usuario

Una de las varias ventaja que tiene Razor es su simpleza, si bien acá no tenemos masterPages propiamente tal, podemos definir la estructura de todas las páginas en nuestro archivo _Layout.cshtml

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <meta name="viewport" content="width=device-width" />

    <title>@ViewBag.Title</title>

    @Styles.Render("~/Content/css")

    @Scripts.Render("~/bundles/modernizr")

</head>

<body>

    @RenderBody()

 

    @Scripts.Render("~/bundles/jquery")

    @Scripts.Render("~/bundles/jqueryui")

    @Scripts.Render("~/bundles/jquerysignalr")

 

    @RenderSection("scripts", required: false)

</body>

</html>

Como vemos incluimos los scripts según el nombre dado en el archivo BundleConfig. Luego un Rendersection para incluir la sección de script propios del comportamiento que queremos lograr en el cliente.

Básicamente tengo dos vistas en el cliente, Envia.cshtml , que hace de backend, en el cual puede visualizar cuando se conecta y desconecta un cliente y Recibe.cshtml , que recibe los mensajes que envía el backend.

Estructura de Envia.cshtml.

@{

    ViewBag.Title = "Envia Mensajes";

}

 

<h2>BackEnd - Enviar Mensajes</h2>

<h2>Mensaje</h2>

 

@using (Html.BeginForm()) {

    @Html.EditorForModel();

 

<input id="send" value="Enviar Mensaje" type="button" />

<ul id="mensajeBackEnd" style="list-style:none;"></ul>

}  

 

@section Scripts { <script src="~/Scripts/MensajeSignalR.js"></script> }

Como ves estoy utilizando el helper que a partir del modelo devuelto en el controlador hacia la vista, que permitirá el render del formulario, ahorrándonos el esfuerzo de construirlo, luego un botón para enviar los datos del formulario y una lista en donde se imprimirán los mensajes de conexión o desconexión de los clientes. La UI queda de esta forma:

image

Estructura de Recibe.cshtml.

Esta vista es mucho más simple, solo tiene la lista para recibir los mensajes:

@{

    ViewBag.Title = "Recibe Mensajes";

}

 

<h2>Cliente - Ver Mensajes</h2>

<ul id="mensajeClient" style="list-style:none;"></ul>

@section Scripts { <script src="~/Scripts/MensajeSignalR.js"></script> }

image

Recordar que tenemos que agregar las acciones en el controlador definido por defecto HomeController:

  public ActionResult Recibe()

        {

       

            return View();

        }

 

  public ActionResult Envia()

  {

      var vm = new Mensaje.Mensaje();

      return View(vm);

   }

Acá ves como se le devuelve a la vista el modelo para que el helper html para crear el formulario pueda hacer el render. Ahora veamos el archivo MensajeSignalR.js, el cual nos da la funcionalidad en el lado del cliente.

$(function () {

    var conn = $.connection("/mensaje");

 

    conn.received(function (data) {

        if (data.Titulo == "Servidor") {

            $("#mensajeBackEnd").append("<li>" + data.Titulo + ':' +
                                                     data.Texto +
"</li>"
);

        } else {

            $("#mensajeClient").append("<li>" + data.Titulo + ':'
                                                      data.Texto +
"</li>"
);

        }

    });

 

    conn.error(function (error) {

        console.warn(error);

    });

 

    conn.start()

        .promise()

        .done(function () {

            $("#send").click(function () {

              var pTitulo = $("#Titulo").val();

              var pTexto = $("#Texto").val();

              conn.send(JSON.stringify({ Titulo: pTitulo, Texto: pTexto }));

            })

        });

});

Como puedes ver , tenemos la función de recibir información “received” dependiendo el titulo decidimos donde imprimir el mensaje (servidor o cliente).

Cuando se inicia una conexión “start”, utilizamos la función promise() de jquery para asegurarnos que la llamada asíncrona se ejecute, si quieres saber más sobre esta función revisa este artículo: http://www.funcion13.com/2012/03/26/comprendiendo-promesas-y-deferreds-en-jquery/. Se presiona el botón (send), y utilizamos el helper JSON para serializar el mensaje.

signal

Funciona perfecto!, más adelante voy a subir otras demos con Hub y algunas un poco más avanzadas.

Puedes descargar la demo completa acá:

DESCARGA/DOWNLOAD

Saludos!
@chalalo

Posted: 15/2/2013 13:48 por Gonzalo Perez | con 1 comment(s)
Archivado en: ,
Comparte este post:

Comentarios

juss3pp3 ha opinado:

Siempre me he preguntado como haces esos gifs xD...

# March 11, 2013 12:27 PM