Thursday, October 16, 2014

SignalR and WebSockets

Intro

WebSocket is a new protocol, developed alongside HTML5, that allows a 2-way communication between client and server. With HTTP and your standard web browsers the communication is all 1-way; the client requests resources from the server and the server serves them. With WebSockets the server can send messages to the client without the client first requesting those resources. Messages can be passed from client to server and from server to client, keeping the socket connection open. Not all the grass is green in this land of Eden though; because this is a newer technology, not all browsers support WebSockets just yet.

This is where SignalR comes in. SignalR is an ASP.Net library that simplifies 2-way communication between the server and the client. It's an implemention of WebSockets, but it's not just that. It will use WebSockets when both the server and client support it, but when one or both does not support WebSockets it will fall back to other technologies that accomplish the same goal in similar ways. Simply put, SignalR allows you to use 2-way communication between client and server using whatever is the best way you are capable of using. Plus, the fallback mechanism happens behind the scenes. This means that you the coder code a single codebase for communication and SignalR makes the choice of which method to use for you. And, one extra bit of info...SignalR allows you to call client-side JavaScript functions from the server. That's some cool stuff!

To the Code!

Create yourself a new Asp.Net web application. Mine's named BlogSignalR1.


Make it an Empty web app with no folders, no core references, and no authentication.

Now add the NuGet package named SignalR.



Now add a class to your project named NotificationHub. Our app will have a single page where we, on the server, can notify our users of things that are about to happen on the website in real-time. This new class is what we'll use on the server-side to send those messages.

Here is the content you'll want for your new class:

using Microsoft.AspNet.SignalR;

namespace BlogSignalR1
{
    public class NotificationHub : Hub
    {
        public void Send(string message)
        {
            Clients.All.broadcastMessage(message);
        }
    }
}


Go ahead and create another new class in your website named Startup. This class will tell Asp.Net to fire up/initialize SignalR. Here's the code for it:

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


Now it's time to work in client-side code a little. First create a new html page in the project. Name the file default.html. Here's the content of that one:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>SignalR Basic User Page</title>
    <!--Reference the jQuery library. -->
    <script src="Scripts/jquery-1.6.4.min.js"></script>
</head>
<body>
    Hi user!
    <div id="notificationArea">

    </div>
    <!--Script references. -->
    <!--Reference the SignalR library. -->
    <script src="Scripts/jquery.signalR-2.1.2.min.js"></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="signalr/hubs"></script>
    <!--Add script to update the page and send messages.-->
    <script type="text/javascript">
        $(function () {
            // Declare a proxy to reference the hub.
            var notification = $.connection.notificationHub;
            // Create a function that the hub can call to broadcast messages.
            notification.client.broadcastMessage = function (message) {
                // Html encode display name and message.
                var encodedMsg = $('<div />').text(message).html();
                // Add the message to the page.
                $('#notificationArea').text(encodedMsg);
            };

            //create a connection to the hub
            $.connection.hub.start().done(function () {
                //sometimes you might need to do something after creating the connection to your hub; for this example, we do not
                });
        });
    </script>
</body>
</html>


This is a very simple page whose sole purpose is to display notifications from a site admin within the div named notificationArea.

Note: there is a possibility your version of either SignalR or JQuery may be different than mine. If so, please modify the script references as necessary to reflect the version you have in your Scripts folder.

The above html file implies we need one more file, this one for admins to create notifications for users. Go ahead and create a new html file called admin.html. Here's the content:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>SignalR Basic Admin Page</title>
    <!--Reference the jQuery library. -->
    <script src="Scripts/jquery-1.6.4.min.js"></script>
</head>
<body>
    Hi Admin!
    <label for="message">Message:</label><input type="text" id="message" />
    <button id="disseminate">Disseminate</button>

    <!--Script references. -->
    <!--Reference the SignalR library. -->
    <script src="Scripts/jquery.signalR-2.1.2.min.js"></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="signalr/hubs"></script>
    <!--Add script to update the page and send messages.-->
    <script type="text/javascript">
        $(function () {
            // Declare a proxy to reference the hub.
            var notification = $.connection.notificationHub;
            // Start the connection.
            $.connection.hub.start().done(function () {
                $('#disseminate').click(function () {
                    // Call the Send method on the hub.
                    notification.server.send($('#message').val());
                    // Clear text box and reset focus for next comment.
                    $('#message').val('').focus();
                });
            });
        });
    </script>
</body>
</html>



Another simple page; one entry where you enter text, one button that you click to get it to push out a notification to clients. Let's try it out!

Go ahead and run the solution, navigate to default.html. Open up a 2nd tab in your browser and navigate to admin.html. Type some text into the entry on the admin page and click the Disseminate button.


Now go back over to the other tab containing default.html and your text is there!

Yes that's right folks, with a little bit of server-side code and a little bit of client-side code, you can create a basic site that allows real-time 2-way communication using SignalR. This is some wonderful technology that has tons of potential uses (chat is the most oft-talked-about usage for SignalR and WebSocket technology). If you want to make sure I'm not fooling you, just drop a breakpoint in your server-side and client-side methods and you'll see the trip from admin.html client, to server-side NotificationHub class, back down to default.html. It's mesmerizing!

What's Next?

Play around with the code and see if you can figure out what all of that JavaScript is doing. I find the best way to dig through stuff is to set breakpoints and trace into it and I'm sure you'll have luck with that method too. You can also dig around in the SignalR documentation and tutorials, as I've provided a link to such beasts down in the Resources section.

Resources

SignalR
WebSocket
My Code

No comments:

Post a Comment