Thursday 13 September 2012

The simplest chat ever with SignalR (and Asp.Net MVC)

Lately I was investigating some technologies for my current project and at some point I was advised to check out the SignalR library. I admit I’ve never heard about it before (shame on me). It was mentioned to me in the context of asynchronous web applications, with the main example being a web chat. Hmm, an interesting exercise I thought! Plus it should give me the general framework understanding. Let’s do it!

It was only later that I realised the chat implementation is the most common example for SignalR usage that you can find on the Web. One more can hurt though, so here is my version :)

Overview

In short, the app works in the following way: people can visit a single chat url and they join our chat automatically. This mean they will see all the messages posted to the chat since they have joined it. They can also post messages that will be seen by other chat members.

I’ve built it as part of a sample MVC4 application, although this could probably be any Asp.Net page, as I’m not using any MVC functionality at all. Two most important parts of this app are the view and the hub. The view displays chat components and handles user actions (i.e. sending messages to the hub). The hub listens for messages and publishes them to all connected clients.

The code

You will need to downlaod the SignalR library for the following code to work. The easiest way to do that is by searching for 'SignalR' in your Nuget package manager.

So I have my Chat controller, which is only used to display the view. As you can see it’s doing nothing else, so the view could probably be a static html page instead:

public class ChatController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

It’s a web chat, so we need some input fields for nickname & message. We also need an area for displaying our conversation. All these belong naturally to our view:




Now that we have basic visual components, let’s make them work. Firstly, we need to reference jQuery & SignalR libraries. I have those defined as bundles in my MVC app, but you can reference all files directly:

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/SignalR")
Notice the third reference - we reference a script, that doesn’t physically exist. SignalR will handle that script request, generating in response javascript code allowing us to communicate with the chat hub. The /signalr part of the uri is configurable.

Now it’s time for the javascript code (see comments for explanation):

$(function () {
    // get the reference to chat hub, generated by SignalR
    var chatHub = $.connection.chat;
 
    // add a method that can be called by the hub to update the chat
    chatHub.publishMessage = function (nick, msg) {
        var chatWin = $("#chatWindow");
        chatWin.html(chatWin.html() + nick + ": " + msg );
    };
    
    // start the connection with the hub
    $.connection.hub.start();
    
    $(document).keypress(function (e) {
        if (e.which == 13) {
            // when the 'Enter' key is pressed, send the message to the hub
            chatHub.sendMessage($("#nick").val(), $("#message").val());
            $("#message").val("");
        }
    });
});
The hub code could not be any simpler. We need to implement a method that can be called by a client wishing to send a message. The method broadcasts that message to all connected clients:
public class Chat : Hub
{
    public void SendMessage(string nick, string message)
    {
        Clients.PublishMessage(nick, message);
    }
 }
In case you haven't noticed yet: we execute a hub server method from our client javascript code (see line 17 of js code) and the other way around i.e. client side js function from our C# hub code (see line 5 of hub code). How cool is that?!?

I must say I'm pressed how easy it is to use for programmers. If you are wondering how it's working under the hood I recommend you reading SignalR documentation on their GitHub page. And finally, here's the screenshot I've taken testing that chat using 2 different browsers:

You can download my VC2012 solution from here: DOWNLOAD.

1 comment:

An Phạm said...

Very helpful for group chat! :3
but how i can private chat one to one ? can you write a tutorial about it !