Web em tempo Real com SignalR
A motivação deste post foi uma discussão aqui na W7BR, como fazer um site enviar uma notificação para os clientes (browsers) sem que os clientes não fiquem dando refresh na página? Foi ai que resolvi pesquisar um pouco e me deparei com SignalR.
SignalR é uma biblioteca Async para .NET para ajudar a criar aplicativos web interativos em tempo real e multiusuários, que está sendo desenvolvido pela equipe do ASP.NET, e segundo o vídeo do Scott Hanselman no TechDays da Rússia, deverá ser incluído nas versões futuras da plataforma ASP.Net, e deve ficar do lado do ASP.Net API.
SignalR é voltado para web e requer do lado do cliente o jQuery 1.6 (ou superior) e do lado do servidor o ASP.NET. A instalação do SignalR é bastante simplificada e pode ser feita via NuGet ou baixado direto do repositório do GitHub em http://github.com/SignalR/SignalR.
Agora que você já conhece o SignalR que tal um exemplo simples para entender seu funcionamento?!
Como de costume o código deste exemplo está no meu GitHub, e você pode ver uma demo do Chat SignalR.
Primeiro vamos criar um novo projeto no Visual Studio 2012 do tipo ASP.NET MVC 3 Web Application, em seguida escolha o template Empty, e adicione um novo controller chamado Home, e uma nova empty View para a action Index do controller Home.
Agora vamos instalar o SignalR via NuGet
PM> Install-Package SignalR
Ele já ira instalar todas as dependencias automaticamente, porém em meus testes, eu precisei instalar a biblioteca JSON2, que é um dependência do SignalR para rodar em IE8, mas mesmo em outros browser não rodou em meus testes sem o JSON2, pelo sim e pelo não, vamos instalar o JSON2, para isso basta usar o NuGet:
PM> Install-Package JSON2
Agora que temos tudo que precisamos instalado, vamos a criação da classe que será utilizada como HUB do SignalR, para isso adicione uma nova pasta em nosso projeto, chamada Hubs, e crie uma nova classe denominada Chat.cs
using System; using SignalR.Hubs; namespace ChatSignalR.Hubs { public class Chat : Hub { //Deve ter um metodo EnviarMensagem no JavaScript public void EnviarMensagem(string mensagem) { mensagem = "<em>" + DateTime.Now.ToString("HH:mm:ss") + "h</em> " + mensagem; //Chama um metodo implementado no cliente via JavaScritp Clients.adicionarMensagem(mensagem); } } }
Todos os nossos métodos públicos na nossa classe Chat devem corresponder a um método JavaScript no cliente, ou no mínimo, qualquer método chamado no objeto JavaScript deve ter um método correspondente na classe Chat no servidor.
Para enviar dados para o cliente, o código de servidor usa a propriedade Clients da classe de Hub. Os membros do Clients, são dinâmicos, aceitando qualquer nome de método, desde que esse método seja exposto do lado do cliente, no nosso caso, o Clients.adicionarMensagem().
Agora que construímos nossa implementação do lado do servidor temos que criar a implementação do lado do cliente, para isso abra a view Index.cshtml do controller Home e adicione o código a seguir:
@{ ViewBag.Title = "ChatSignalR"; } <script type="text/javascript" src="@Url.Content("></script> <!-- Referencia para o SignalR --><script type="text/javascript" src="@Url.Content("></script> <!-- Neste script que é criado em tempo de execução que ocorre toda a mágica --> <script type="text/javascript" src="@Url.Content("></script><script type="text/javascript">// <![CDATA[ $(function () { // Cria um proxy da nossa classe Chat do Servidor var chat = $.connection.chat; // Declare a function on the chat hub so the server can invoke it chat.adicionarMensagem = function (message) { $('#mensagens').append(' <li>' + message + '</li> '); }; $("#btnEnviar").click(function () { // Chama o metodo da classe Chat do servidor chat.enviarMensagem($('#msg').val()); }); // Inicia a conexão $.connection.hub.start(); }); // ]]></script></pre> <div><input id="msg" type="text" /> <input id="btnEnviar" type="button" value="Enviar" /></div> <pre>
O interessante é que os dois primeiros scripts fazem referencia a um arquivo específicos. Já o terceiro (~/signalr/hubs) faz referencia ao conteúdo que é gerado em tempo real, e que depende da nossa implementação do código que temos nos nossos Hubs, no caso a nossa classe Chat.cs.
Bom pessoal, era isso que tinha para mostrar e o que eu consegui descobrir até o momento, mais já da para ver o potencial desta biblioteca, uma vez que com esse tipo de implementação não precisamos ficar consumindo recursos desnecessários do servidor (refresh) e de quebra podemos enviar mensagens aos clientes que estão com suas páginas abertas.
Já estamos pensando em implementar algo, o usuário esta em um site de notícias, o administrador cadastra uma nova notícia, no mesmo instante mandamos uma notificação para todos os clientes com o link da nova notícia, ao invés de fazer um refresh da página de tempos em tempos, com isso só consumimos recursos se realmente tiver novos conteúdos.