Introdução

Neste artigo você aprenderá a criar uma simples Sala de Bate Papo usando as bibliotecas SignalR e Knockout.js.

SignalR é uma biblioteca do ASP.NET que simplifica o processo de criação de aplicações que necessitam de comunicação em tempo real entre o cliente e o servidor. É composto por um framework ASP.NE e de uma API Javascript.

Knockout.js é uma biblioteca Javascript que simplifica o desenvolvimento de interfaces que seguem o padrão Movel-View-ViewModel.

Vamos criar essa aplicação de Sala de Bate Papo do zero. Veja os passos necessários:

  • Adicionar a biblioteca SignalR e Knockout.js
  • Criar o Hub de mensagens.
  • Usar as bibliotecas SignalR e Knockout.js.

O resultado da nossa aplicação será este:

9-15-2013 9-39-58 PM

Referências

Este artigo baseia-se no tutorial Getting Started with SignalR (C#) e no site Learn Knockout.js

Adicionar as bibliotecas SignalR e Knockout.js

Crie uma ASP.NET Web Empty Web Application, acesse o menu Tools > Library Package Manager > Package Manager Console e por fim execute os seguintes comandos no Package Manager Console:

9-15-2013 9-16-00 PM

PM> Install-Package Microsoft.AspNet.SignalR
PM> Install-Package knockoutjs
PM> Install-Package jquery

Adicione um arquivo Global.asax e adicione o método RouteTable.Routes.MapHubs() ao evento Application_Start():

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;

namespace ChatApp
{
    public class Global : System.Web.HttpApplication
    {
        public void Application_Start()
        {
            RouteTable.Routes.MapHubs();
        }
    }
}

Criar Hub de Mensagens

O framework SignalR possui uma classe chamada Hub que é usada para definir os métodos de comunicação entre o cliente e o servidor..
A maneira correta de usar esta classe é através de herança. Você cria uma classe que herda de Hub e implementa métodos que deseja expor para os clientes.

A classe Hub possui uma API que te permite executar os métodos expostos pelo cliente. Você pode literalmente chamar um método Javascript a partir do servidor. Esta tarefa é executada pela classe Clients que possui alguns filtros como “All” e “Others” que te permitem escolher o(s) cliente(s) onde o método Javascript será chamado.

Na classe abaixo o método Enviar(string, string) estará acessível via Javascript através do código $.connection.chatHub.enviar(string, string).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace ChatApp
{
	public class ChatHub : Hub
	{
    	public void Enviar(string usuario, string texto)
    	{
        	Clients.All.EnviarATodos(usuario, texto);
    	}
	}
}

Uma breve explicação do código acima é a seguinte: O método Enviar(string, string) é a chamado por algum cliente Javascript. O método então, captura os parâmetros e chama o método Clients.All.EnviarATodos(string, string) em todos os clientes.
Usar as bibliotecas Javascript do SignalR e Knockout.js

Para a plicação ter uma aparência de sala de bate papo, crie uma página Index.html na raiz do site e substitua a tagpelo seguinte código:

<head>
	<title>SignalR Simple Chat</title>
	<style type="text/css">
    	.content
    	{
        	padding: 1em;
        	background-color: #EEEEDD;
        	border: 1px solid #CCC;
        	max-width: 655px;
    	}
        	.content ul
        	{
            	height: 200px;
            	overflow-y: scroll;
        	}
        	.content input
        	{
            	font-family: Arial;
        	}
        	.content b
        	{
            	font-weight: bold;
        	}
        	.content p
        	{
            	margin-top: 0.9em;
            	margin-bottom: 0.9em;
        	}
	</style>
</head>

O próximo passo é criar o HTML da Sala de Bate Papo. No HTML abaixo temo o atributo data-bind usado pelo Knockout.js.

Alguns detalhes importantes:

O UL com id igual à “ulMensagens” tem um template de conteúdo, e para cada elemento da lista mensagens será criado um elemento LI. Veja que há um elemento STRONG que possui um data-bind para a propriedade text pela variável usuário. Dessa forma, o conteúdo é recuperado do elemento da lista mensangens que está sendo processado. O mesmo ocorre com o SPAN.

Há dois elementos INPUT. Um deles para capturar o nome do usuário e outro para capturar a mensagem a ser enviada para a sala de bate papo. Estes dois campos estão vinculados as variáveis usuario e texto.

O outro elemento INPUT é um button que possui o evento CLICK vinculado à função enviarMensagem.

Há um controle de visibilidade do INPUT de entrada do nome do usuário que é feito pelo Knockout usando o foco e o clique do botão para decidir qual elemento será exibido.

Há um controle para habilitar ou desabilitar o botão de enviar usando a quantidade de caracteres da variável texto.

Insira este código logo após a tag:

<div class="content">
    <ul id="ulMensagens" data-bind="foreach: mensagens">
        <li>
            <strong data-bind="text: usuario"></strong>:&nbsp;<span data-bind="    text: texto"></span>
        </li>
    </ul>
    <p>
        <b data-bind="visible: !estaEditando(), text: usuario, click: editar">&nbsp;</b>
        <input data-bind="visible: estaEditando, value: usuario, hasFocus: estaEditando" />
    </p>
    <input data-bind="value: texto, valueUpdate: 'afterkeydown', hasFocus: estaSelecionado" />
    <input type="button" value="Enviar" data-bind="click: enviarMensagem, enable: texto().length > 0" />
</div>

O próximo passo é referenciar as bibliotecas Javascript. Acrescente este código depois do DIV content:

<script src="/Scripts/jquery-2.0.3.min.js"></script>
<script src="/Scripts/jquery.signalR-1.1.3.js"></script>
<script src="/Scripts/knockout-2.3.0.js"></script>
<script src="/signalr/hubs"></script>

Se você notar problemas na URL “/SignalR/Hubs” verifique o Global.asax.

Após os scripts acima. Crie o seguinte Script:

<script type="text/javascript">
    $(function () {
        ko.extenders.scrollFollow = function (target, selector) {
            target.subscribe(function (newval) {
                var el = document.querySelector(selector);
                if (el.scrollTop == el.scrollHeight - el.clientHeight) {
                    setTimeout(function () {
                        el.scrollTop = el.scrollHeight - el.clientHeight;
                    }, 0);
                }
            });
            return target;
        };
        function Mensagem(_usuario, _texto) {
            this.usuario = _usuario;
            this.texto = _texto;
        }
        function BatePapoViewModel() {
            this.usuario = ko.observable("Digite seu nome");
            this.texto = ko.observable("Digite sua mensagem");
            this.estaSelecionado = ko.observable(true);
            this.mensagens = ko.observableArray().extend({
                scrollFollow: '#ulMensagens'
            })
            this.estaEditando = ko.observable(false);
            this.editar = function () {
                this.estaEditando(true)
            }
            this.enviarMensagem = function () {
                var chatHub = $.connection.chatHub;
                chatHub.server.enviar(this.usuario(), this.texto());
                this.texto("");
                this.estaSelecionado(true);
            };
        }
        var chatHub = $.connection.chatHub;
        chatHub.client.EnviarATodos = function (usuario, texto) {
            sala.mensagens.push(new Mensagem(usuario, texto));
        };
        $.connection.hub.start();
        var sala = new BatePapoViewModel();
        ko.applyBindings(sala);
    });
</script>

Download e Demo

Você pode baixar a aplicação no meu Skydrive.
Veja algumas telas:

9-15-2013 9-38-44 PM  9-15-2013 9-36-40 PM 9-15-2013 9-37-00 PM 9-15-2013 9-37-20 PM 9-15-2013 9-38-12 PM9-15-2013 9-39-58 PM

Conclusão

Com a biblioteca SignalR você pode criar uma aplicação que troca informações entre os clientes e o servidor de uma forma bem simples e natural. O framework Knockout.js te permite criar interfaces dinâmicas seguindo o padrão Model-View-ViewModel.