code – Demo Panel comentarios Parte 2 – Mvc SignalR

Solucion demo panel de comentarios

Artículos relacionados

Introducción

En el post anterior se terminó de desarrollar la presentación que va a tener la UI del panel de comentarios desarrollada con ReactJs. En este post veremos la integración con MVC y SignalR. En la parte de MVC veremos cómo crear Actions para devolver y registrar datos, por el momento en memoria. Por el lado de SignalR veremos cómo crear una clase Hub para notificar a todos los clientes cada vez que alguien agregue un nuevo comentario.

Configuración SignalR

Vamos al Administrador de paquetes de Nuget y agregamos la referencia de los paquetes  Microsoft.Owin y Microsoft.AspNet.SignalR al proyecto web.

Referencia SignalR

Agregamos una clase llamada Startup, dentro de la carpeta App_Start, que se encarga de configurar el uso de SignalR en el sitio web y copiamos el siguiente código.

using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(PanelComentario.Startup))]
namespace PanelComentario
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

SignalR Hub

En la raíz de proyecto creamos una carpeta llamada Hubs y dentro una clase llamada CommentarioHub con el siguiente código:

using Microsoft.AspNet.SignalR;

namespace PanelComentario.Hubs
{
    public class ComentarioHub : Hub
    {
    }
}

Esta clase será la encargada de devolver la respuesta desde el servidor a la UI cada vez que se agregue un nuevo comentario.

MVC

En la carpeta Models agregamos una clase llamada ComentarioModel y agregamos el siguiente código:

namespace PanelComentario.Models
{
    public class ComentarioModel
    {
        public string Identificador { get; set; }
        public string FechaHora { get; set; }
        public string Autor { get; set; }
        public string Texto { get; set; }
    }
}

De nuevo en la carpeta Models agregamos una clase llamada RepositorioInMemoryComentario encargada de manejar los datos en memoria, a esta clase le agregamos el siguiente código:

using System.Collections.Generic;
using System.Linq;

namespace PanelComentario.Models
{
    public static class RepositorioInMemoryComentario
    {
        private static readonly IList<ComentarioModel> comentarios;
        static RepositorioInMemoryComentario()
        {
            comentarios = new List<ComentarioModel>
            {
                new ComentarioModel
                {
                    Autor = "Scrumcito",
                    Texto = "Apliquemos scrum a todo",
                    FechaHora="11/11/2011 11:11:11",
                    Identificador="4321"
                },
                new ComentarioModel
                {
                    Autor = "ArquitectoPpt",
                    Texto = "Todo esta en la ppt",
                    FechaHora="12/12/2012 12:12:12",
                    Identificador="1234"
                }
            };
        }
        public static void Agregar(ComentarioModel comentario)
        {
            comentarios.Add(comentario);
        }
        public static IList<ComentarioModel> TraerTodo()
        {
            return comentarios.Reverse().ToList();
        }
    }
}

En la controladora PanelController agregamos el siguiente método para devolver todos los comentarios:

[OutputCache(Location = OutputCacheLocation.None)]
public ActionResult Comentarios()
{
    return Json(RepositorioInMemoryComentario.TraerTodo(),
JsonRequestBehavior.AllowGet);
}

Ahora agregamos el método encargado de registrar los comentarios en la controladora PanelController:

[HttpPost]
public ActionResult Comentario(ComentarioModel comentario)
{
    comentario.Identificador = Guid.NewGuid().ToString();
    RepositorioInMemoryComentario.Agregar(comentario);
    NotificarComentarioNuevo();
    return Content(comentario.Identificador);
}

Para notificar a todos los clientes cuando se agregue un nuevo comentario agregamos el siguiente método:

private static void NotificarComentarioNuevo()
{
    // Recupera el contexto del Hub comentario, este contiene la referencia
    // de todos los clientes que se han conectado
    var hubContext = GlobalHost.ConnectionManager.GetHubContext<ComentarioHub>();

    // Notifica a todos los clientes llamando al método agregarComentario
    // y devuelve todos los comentarios registrados, el metodo se encuentra
    // en el archivo PanelComentario.jsx
    hubContext.Clients.All
      .agregarComentario(RepositorioInMemoryComentario.TraerTodo());
}

Finalmente, vamos a la vista Panel/Index.cshtml y agregamos los siguientes scripts debajo de la llamada de jQuery para hacer las llamadas al Hub de Comentarios en SignalR:

<script src="~/scripts/jquery-2.2.0.js"></script>
<!-- Cambio -->
<script src="~/scripts/jquery.signalR-2.2.0.js"></script>
<script src="~/signalr/hubs"></script>
<!-- Cambio -->
<script src="https://fb.me/react-0.14.0.js"></script>

React JS

Abrimos el archivo Scripts/App/RegistroComentario.jsx y modificamos el contenido de la función submitComentario por el siguiente código:

submitComentario: function (e) {
    e.preventDefault();
    // this.refs : es un identificador que sirve para buscar elementos
    var autor = this.refs.autor.value.trim();
    var texto = this.refs.texto.value.trim();
    if (!texto || !autor) {
        return;
    }
    this.props.enviarComentario({ Autor: autor, Texto: texto });
    this.refs.autor.value = '';
    this.refs.texto.value = '';
    return;
}

Nota: Para más información acerca de atributo refs recomiendo leer el siguiente enlace.

Ahora modificamos el script PanelComentario.jsx con el siguiente código:

"use strict"
var PanelComentario = React.createClass({
    cargarComentariosAPI: function () {
        var xhr = new XMLHttpRequest();
        xhr.open('get', this.props.cargarComentariosUrl, true);
        xhr.onload = function () {
            var data = JSON.parse(xhr.responseText);
            this.setState({ comentarios: data });
        }.bind(this);
        xhr.send();
    },
    enviarComentarioAPI: function (comentario) {
        var comentarios = this.state.comentarios;
        comentarios.unshift(comentario);
        this.setState({ comentarios: comentarios });
        var data = new FormData();
        data.append('Autor', comentario.Autor);
        data.append('Texto', comentario.Texto);
        var xhr = new XMLHttpRequest();
        xhr.open('post', this.props.envioComentarioUrl, true);
        xhr.send(data);
    },
    comentarioAgregadoAPI: function (comentarios) {
        this.setState({ comentarios: comentarios });
    },
    getInitialState: function () {
        return { comentarios: [] };
    },
    componentWillMount: function () {
        this.cargarComentariosAPI();
    },
    componentDidMount: function () {
        // Registro del cliente al Hub Comentario de SignalR
        // Acá se define la función de JS que se debe invocar
        // cuando se llame al método agregarComentario desde el servidor
        var comentarioHub = $.connection.comentarioHub;
        $.connection.hub.start();
        comentarioHub.client.agregarComentario = this.comentarioAgregadoAPI
    },
    render: function () {
        return (
<div className="panelComentarios">
<h1>Panel de comentarios</h1>
<RegistroComentario enviarComentario={this.enviarComentarioAPI}/>
<ListaComentario comentarios={this.state.comentarios} /></div>
);
    }
});

NOTA: Para más detalle sobre los métodos  componentDidMount, componentWillMount, getInitialState y render los invito a leer este artículo.

Para terminar con los componentes de ReactJs abrimos el script Main.jsx y copiamos el siguiente código:

"use strict";
ReactDOM.render(
<PanelComentario envioComentarioUrl="/panel/comentario" cargarComentariosUrl="/panel/comentarios" />
, document.getElementById("contenido"));

Ahora para ver que todo esté bien compilamos la solución, presionamos f5 y navegamos a la url Panel/Index y debemos ver el panel de comentarios en pantalla.

El código puede ser descargado desde este enlace.

Referencias:
Metal Tip:

Este artículo lo escribí escuchando la canción War Pigs de la banda Black Sabbath de Inglaterra, les comparto el enlace.

Happy coding and Stay Heavy lml

Deja un comentario