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

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s