Click here to Skip to main content
14,111,439 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

132.2K views
6.7K downloads
67 bookmarked
Posted 7 Aug 2013
Licenced CPOL

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

, 7 Aug 2013
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Zhuyun Dai
Architect
China China
Over 10-years experience in using Microsoft technologies.
At present, working as the architect of a clustered real-time data delivery and visualization system, responsible for the design of component architecture, product packaging and deployment, also targeting private cloud solutions for future.

You may also be interested in...

Comments and Discussions

 
Question5 out of 5 Pin
rohit kakria14-Mar-15 6:33
memberrohit kakria14-Mar-15 6:33 
GeneralMy vote of 4 Pin
praveen Ojectnext28-Oct-14 21:12
memberpraveen Ojectnext28-Oct-14 21:12 
Questiongetting error Pin
Rahul AnilKumar Mehta4-Jun-14 4:44
memberRahul AnilKumar Mehta4-Jun-14 4:44 
QuestionWhere is service code Pin
qpari4-Jun-14 1:06
memberqpari4-Jun-14 1:06 
QuestionWinForms and SignalR Pin
kiquenet.com12-Aug-13 1:34
professionalkiquenet.com12-Aug-13 1:34 
Questionconfusion after read your code Pin
Tridip Bhattacharjee8-Aug-13 4:50
professionalTridip Bhattacharjee8-Aug-13 4:50 
AnswerRe: confusion after read your code Pin
RichardGrimmer9-Aug-13 0:43
memberRichardGrimmer9-Aug-13 0:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190518.1 | Last Updated 7 Aug 2013
Article Copyright 2013 by Zhuyun Dai
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid