Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET SignalR Basis Step by Step (Part 1)

0.00/5 (No votes)
7 Aug 2013 2  
Recognize and learn to use SignalR basis

Introduction

In this article, I will introduce the very basic knowledge of ASP.NET SignalR I have learnt recently and demonstrate the simplest demo (SignalREcho_no_packages.zip) using PersistentConnection step by step. Note that I have deleted the packages folder from the solution because the size is too big for uploading. You could fetch Microsoft.AspNet.SignalR locally via NuGet for build. OK, let’s start from some basic questions.

What can ASP.NET SignalR do?

  • Server pushes data to client in HTTP connection
  • Server to client RPC in HTTP connection
  • Easily scale out via SQL Server, Redis or Service Bus

What technologies does SiganlR use to transfer data?

  • Using WebSockets if it is available
  • Otherwise, using other technologies, e.g. long polling

What kind of data does SignalR support to transfer?

  • Non-compressed JSON text or plain text
  • If you want to transfer compressed JSON or BSON or your binary data, you have to encode and decode the data (e.g. using Base64) or to implement IJsonSerializer by your own logic on the server side and implement the same logic on the client side. Note that TextReader and TextWriter are used inside SignalR. That means you have to convert your data to text before transferring anyway.

The current stable version is 1.1.3. Version 2.0 is in Beta. The license is Apache 2.0. The official web site is http://signalr.net. The documentation can be found here.

Packages

All SignalR development packages can be fetched through NuGet. Normally, you just need to fetch Microsoft.AspNet.SignalR (Package ID) which contains most of the components you need, including:

  • Microsoft.AspNet.SignalR.Core: server side components used to build SignalR endpoints.
  • Microsoft.AspNet.SignalR.Owin: OWIN host for SignalR.
  • Microsoft.AspNet.SignalR.SystemWeb: used to host SignalR in ASP.NET (via OWIN ASP.NET host).
  • Microsoft.AspNet.SignalR.Js: JavaScript client for SignalR.
  • Dependencies are also included: jQuery, Newtonsoft.Json, Microsoft.Owin.Host.SystemWeb, Microsoft.Web.Infrastructure and OWIN.

You could fetch other SignalR packages when you need:

  • Microsoft.AspNet.SignalR.Client: .NET client for SignalR (includes WinRT, WP8 and Silverlight5).
  • Microsoft.AspNet.SignalR.Redis: Redis messaging backplane for scaling out SignalR in web farm.
  • Microsoft.AspNet.SignalR.ServiceBus: Windows Azure Service Bus messaging backplane for scaling out SignalR in web farm.
  • Microsoft.AspNet.SignalR.SqlServer: SQL Server messaging backplane for scaling out SignalR in web farm.
  • Microsoft.AspNet.SignalR.Sample: used to quickly setup a working sample in your application.

PersistentConnection

PersistentConnection is the core class used to host a SignalR service on the server side. Let me demonstrate how to use it.

First, I create a new ASP.NET web application and use NuGet to fetch the Microsoft.AspNet.SignalR package. Then, I define a new class inherited from PersistentConnection:

public class MyConnection : PersistentConnection 
{
    protected override Task OnConnected(IRequest request, string connectionId)
    {
        string msg = string.Format(
            "A new user {0} has just joined. (ID: {1})",  
            request.QueryString["name"], connectionId);
        return Connection.Broadcast(msg);
    }
    protected override Task OnReceived(IRequest request, string connectionId, string data)
    {
        // Broadcast data to all clients
        string msg = string.Format(
            "{0}: {1}", request.QueryString["name"], data);
        return Connection.Broadcast(msg);
    }
}

OnConnected is called when a client connects to my service. Connections are differentiated by connection IDs (GUID). The client can pass some information through IRequest.QueryString when the connection is established. We can also get other HTTP items like cookies, posted form, headers and user principal from IRequest. Note all these items belong to the first request which requests to establish the connection.

OnReceived is called when client data is arrived. connectionId tells which connection the data comes from. The data is in text format. You have to parse it by yourself if it does not represent plain text.

PersistentConnection.Connection provides the Broadcast method to send a message to all connected clients; it also provides the Send method to send a message to a specific connection or a group (using the group name as connectionId). Both methods support an excluded list for connections that we don’t want to send messages to.

We can register our service to the route table in Global.asax using MyConnection:

public class Global : System.Web.HttpApplication 
{
    protected void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapConnection<MyConnection>("echo", "/echo");
    }
} 

Now we can write JavaScript in a web page to connect to our service:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head> 
    <title>SignalR Echo</title>
    <script type="text/javascript" src="Scripts/jquery-2.0.3.min.js"></script>   
    <script type="text/javascript" src="Scripts/jquery.signalR-1.1.3.min.js"></script>
</head>
<body>
    <script type="text/javascript">
        function htmlEncode(value) {
            return $("<div/>").text(value).html();
        }
        
        function addMsg(msg) {
            $("#messages").append("<li>" + htmlEncode(msg) + "</li>");
        }
        $(function () {
            $("#join").click(function () {
                var connection = $.connection("/echo", "name=" + $("#name").val(), true);;
                
                connection.received(function (data) {
                    addMsg(data);
                });
                connection.error(function (err) {
                    addMsg("Error: " + err);
                });
            
                addMsg("Connecting...");
                connection.start(function () {
                    addMsg("Connected.");
                    $("#send").click(function () {
                        connection.send($("#msg").val());
                    });
                });
            });
        });
    </script>
    <table>
        <tr>
            <td><span>Name:</span></td>
            <td><input type="text" id="name" /></td>
            <td><input type="button" value="Join" id="join" /></td>
        </tr>
        <tr>
            <td><span>Message:</span></td>
            <td><input type="text" id="msg" /></td>
            <td><input type="button" value="Send" id="send" /></td>
        </tr>
    </table>
    <ul id="messages"></ul>
</body>
</html>  

Next let’s create a .NET client. Just create a new console application and use NuGet to fetch the Microsoft.AspNet.SignalR.Client package. In Main, I use the Connection class to communicate with our service:

class Program  
{
    private const string ServiceUri = "http://localhost:12722/echo";
    static void Main(string[] args) 
    {
        var connection = new Connection(ServiceUri, "name=dzy");
        connection.Received += connection_Received;
        connection.StateChanged += connection_StateChanged;
        Console.WriteLine("Connecting...");
        connection.Start().Wait();
        string inputMsg;
        while (!string.IsNullOrEmpty(inputMsg = Console.ReadLine()))
        {
            connection.Send(inputMsg).Wait();
        }
        connection.Stop();
    }
    static void connection_StateChanged(StateChange state)
    {
        if (state.NewState == ConnectionState.Connected)
        {
            Console.WriteLine("Connected.");
        }
    }
    static void connection_Received(string data)
    { 
        Console.WriteLine(data);
    }
} 

To see whether the service is running on WebSockets or long polling, we can host the service on both IIS 7.5 and IIS 8.0 on Windows 8 or Windows Server 2012. Note that .NET WebSockets only works on Windows 8, Windows Server 2012 and above. Then, we can use Fiddler to check the HTTP requests on the client machine.

If the service is hosted on IIS 7.5, the connecting request keeps alive:

If the service is hosted on IIS 8 on Windows 8 or Windows Server 2012, the connecting request asks for upgrading to WebSocket connection:

Summary

In the next part, I will introduce SignalR Hubs, Scaling Out and Extensibility.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here