Real-Time Web Enablement with SignalR in .Net

June 24, 2013 § 3 Comments

Here is good article on SignalR in .Net from Sonal Arora

Real-Time Web Enablement with SignalR in .Net

We know that Twitter is the classy example of the real-time web and we can find the latest idea, stories, trends and what not on Twitter as it happens. But then again what is real-time web and what is so gripping about it? The real-time web is fundamentally different from real-time computing since there is no knowing when, or if, a response will be received1 and HTTP being a stateless protocol, the server does not have any connection with the client once a response is sent back. So how can a server make its connected client update with some information when the client has not asked for it and can I achieve it for my web application to make it trendy? The Answer is Yes… read on to learn more about the Enabler, SignalR.

So What is SignalR

Real-time web functionality is the ability to have server-side code push content to connected clients instantly as and when required2 and ASP.NET SignalR is a library that enables applications to include real-time web as a feature in no time. It offers a simple to use, high-level API for making server to client RPC in ASP.NET applications, through which we can call JavaScript functions in clients’ browsers from our server-side .NET code. Enhancing it for connection management, e.g. connect/disconnect actions, grouping connections, authorization is also doable with SignalR, although Authorization is not offered out of the box here.

It is an Open Source library and currently licensed under the Apache License, Version 2.0. One may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

How SignalR Works

SignalR is something that sits a layer above all of the different techniques of transport whether it’s Web Sockets or AJAX long polling or server-sent events. I, as a developer, code against the SignalR API, and SignalR takes care of ensuring that the appropriate persistent connection passage is set up and maintained between the browser and the server. So it is like layered abstraction over a connection.

When an application has a SignalR connection and it wants to send some data to the server, data is not sent in a raw form; SignalR wraps that data in some JSON along with other information and wraps it all on the JSON payload before sending it to the server. Similarly on the server side, when an app broadcasts data to all connected clients, it does not just broadcast the raw data but a bunch of framing information that contains connection information as well.

A typical request header sent through SignalR client could be something like the following.

POST/signalr/send?transport=foreverFrame&connectionId=ba0c3fe4-1a34-48b4-9a3a-8c7cdc02b5d9 HTTP/1.1

It has transport type (Web socket/Forever frame etc.), Connection Id and HTTP protocol information.

Most of SignalR pieces are replaceable with customized implementations. You can check more athttps://github.com/SignalR/SignalR/wiki/Extensibility

SignalR consists of a client-side library and a server-side library that work together; let’s check these one by one.

Server

There are two programming prototypes of servers possible with SignalR.

Two programming prototypes of servers
Two programming prototypes of servers

  • Persistent Connections
    Persistent connection, the simpler of the two possibilities, provides mechanisms to alert the connection and disconnection of users, and to manage asynchronous messages to linked users, both individually and collectively. In this kind of implementation, your endpoint or server derives from PersistentConnection class.
  • Hubs
    Hubs provide a development interface, which is much easier to use. The integration between client and server is almost seamless. Hubs provide a higher level RPC framework over a PersistentConnection. It is advisable to use when the application has different types of messages that need to be sent between servers. We can create the same applications using persistent connections, but with hubs it will be simpler.

And Self Host

Any .NET application (console, forms, Windows services…) can act as the host of SignalR services. In case you want to run your host outside IIS, you can code for having Self host.

Client

The SignalR JavaScript client comes in the form of a jQuery plugin. However, SignalR does not just have JavaScript client library. It is also possible to find client components for Windows Phone, Silverlight, WinRT or generic .NET clients, which extends the range of SignalR’s applicability as a framework for real-time applications in any kind of scenario.

Different client components currently available are:

  • Javascript
  • .NET 4.0
  • .NET 4.5
  • Silverlight 5
  • WinRT
  • Windows Phone 8

SignalR features
SignalR features

Transport

SignalR is built upon the idea of transports; every transport mode decides how data is sent /received and how it connects and disconnects. SignalR supports multiple transport modes with the assigned priority. If the client’s browser supports Web Socket transport then communication happens in this mode else it falls back to Server Sent or Forever frame; if browser does not support these two then it makes use of the long polling mode for communication.

Multiple transport modes
Multiple transport modes

Though SignalR tries to choose the “best” connection supported by the server and client, nevertheless you can also force it to use a specific transport. At the time of starting the connection, you specify transport mode as:

  1. //try only longpolling
  2. connection.start({ transport: ‘longPolling’ });
  3. // try longPolling then webSockets
  4. connection.start({ transport: [‘longPolling’,’webSockets’] });

The Magical Connection ID

When an app is using SignalR, every connected client is assigned a connection id, which is regenerated at every page refresh. The server identifies the calling client and other connected clients with the help of this connection id only. Any connected client can invoke a server method from the script with the help of proxy handler. And at the server end, along with the relevant processing, a client side method can be invoked. That makes it a Bi-Directional RPC, where one client invokes a server method defined on the hub and from this server method you can invoke methods at all/selected/calling client.

Where can I use SignalR?

SignalR works deliciously for simple notifications where we need to update all connected users for some news feed and broadcasting. However it can handle complex scenarios such as Chat, Co-Creating, Gaming, etc. Here is the small snapshot of the usability scenario.

Notification

Chat

Co-Create

Gaming

Notify All or selected clients.

Notification could be of numerous types, like incoming message, some alert, progress bar, reminders, comment or feedback on your blog or post, etc.

It is easy to implement chat with the help of SignalR. Chat can be one-to-one or Group chat. You can try out a simple chat application as described here:http://www.asp.net/signalr/overview /getting-started/tutorial-getting-started-with-signalr Two or more connected users can enter into co-create mode similar to the one described here:http://www.codeproject.com/Tips /417502/Online-Whiteboard-using-HTML5-and-SignalR It enables applications like gaming, which require high frequency push from the server. You can check out the example given on the SignalR site:

http://shootr.signalr.net/

Perspective

SignalR and its usability looks very promising; it lets developers embed real-time web in the application without getting their hands dirty. It’s on GitHub and there is a dedicated team working tirelessly to make it even better. New users get instant support on the forums as well. To get hands on with this very promising library from Asp.net, read Part 2 of this article to know how to actually do that.

References

1.        Real Time Web. Wikipedia”

2.        Introduction. “SignalR

 

Getting Started with SignalR

Your app should be on .Net Framework 4.0 or higher in order to use SignalR. You can find it on NuGet. To install SignalR in your .Net Application, click on Tools | Library Package Manager | Package Manager Console in your VS IDE and run the command:

  1. install-package Microsoft.AspNet.SignalR

This command will add Server and Client side libraries in your application, making you ready to go.

Add Server and Client side libraries

Add Server and Client side libraries

Follow these steps to get hands on with SignalR with one simple example.

Adding Reference to SignalR

Add reference to SignalR in your class file.

  1. using Microsoft.AspNet.SignalR;

Implementing the Endpoint

The endpoint, or SignalR service, can be implemented using persistent connection or hubs. I will be implementing Hubs in the example.

Example Code

Route Registration

Once the endpoint is implemented, we must register it in the routing system, which will allow us to access it. The best place to do this is in the Application_Start() of Global.asax, so that it runs during initialization of the application.

Example Code

Implementing the Web Client

Implementing the web client begins by including a reference to the client library of this component on our page or view. In order to support older clients that do not natively support JSON deserialization, you will have to add a reference to the json2.js script library before referencing SignalR related script files.

Example Code

Initiate the Connection

To initiate a connection from client to server, you need to start the hub in script. Along with initiating connection you would want to define the event that triggers the server push; it could be anything from a button click or some status change. To keep it simple, in the example it’s a button click on your page.

Example Code

Defining Client Procedure to be Invoked by Server

If you recall from the “Implementing the endpoint” step, I had called a method broadcastMessage ()on all the clients. The definition of this method is done in the script at the client side as shown below.

Example Code

Now run the application in multiple browser windows and click at the button control on one page. This will display “Hello <User  Name> Welcome to Devx” in <YOUR HTML CONTROL> in opened browser windows, even for those that were not active.

So far so good, without worrying about the rawness of transport and real time web intricacies, you made your site RealTime web enabled in no time with SignalR. But is that all you wanted for your site, if not…then read on.

Unraveling Real World Problems with SignalR

Applications in the real world are not as easy as the example we saw just now. To implement real-time web with SignalR, you will have to play around with the connection ids of connected clients. And if authorization is enabled for a web site then you will have to write your own code and save the connection id along with logged in user details, as authorization is not offered here out of the box. Today authorization is more or less an integral part of web sites, and I am not taking up some unexplored topic here. Nevertheless, I would like to detail different strategies to help you choose the best one for your requirement.

Diverse Approaches for Managing Connection IDs

  • DEPRECATED: In its initial releases, SignalR provided a way to override its Connection Factory where a programmer could assign a unique connection id to each connected client and that could be used while invoking the client method; however it is no longer supported.
    http://stackoverflow.com/questions/9606569/signalr-set-clientid-manually
  • Now you will have to save the connection id along with the unique key of the authorized user in order to enable your code to invoke the method on the selected client. A very commonly used design is to maintain a user list on the server that plots connection IDs to users and registers the users as they connect and disconnect1, as proposed at the link http://forums.asp.net/t/1887454.aspx/1?How+to+manually+set+the+connection+id.
  • For application sanity and keeping the app server memory free for processing, I personally suggest using DB tales instead of adding things up in some variable at the app server. The above mentioned concept can be implemented using a DB table we well. I will elaborate this approach in article and at the end suggest some enhancements based on the requirement.

Step 1: Boot up

Here I assume that:

1. You have installed SignalR lib in your .Net application, on framework 4.0 or higher(ref).

2. You have defined your end point by deriving your class from Hub (ref).

3. You have made the necessary changes to your Global.asax (ref).

Step 2: Change in DB Schema

Create one db table to save logged in user’s id along with connection id. Entity class would look something like what is shown below.

Example Code

Step 3: Client and Connection

After including references to the SignalR client library as we did in previous example, you will have to initiate connection. When a client connects to Hub, you can invoke the method to save user information along with connection id. So here we write a client method, which is invoked when the master page or frame window loads.

Example Code

Heremarkonline() is a server side method in your Hub class, to store User and connection id info in the table.

Example Code

Once we are done with “Setting up the connection,” which includes saving rows to db schema, we should implement logic to clear the table as and when the user disconnects from application.

Now disconnection can happen in two manners. The user can close the browser or can log off. To handle both scenarios, you can write methods similar to those shown below.

In the class that derives from Hub, override onDisconnected().

Example Code

And when a user logs off from the application, invoke a method similar to the one shown below.

Example Code

Step 4: Updating DB Schema

Code for updateOnlineUser()method is shown below.

Example Code

Step 5: Fetching a User’s Connection ID/s

Now write a code that fetches all connection ids for a specific user.

Example Code

Step 6: Client-Server BI Directional RPC

Now whenever a server method is invoked, you can fetch list of available connection ids for the target user/s and invoke the method on available connection ids.

Example Code

Where broadcastMessage is a client side method defined as:

Example Code

The above mentioned code will work even If you have multiple connection id scenarios like notification, chat and Co-Create on the same screen, working parallel to each other.

Multiple connection id scenarios
Multiple connection id scenarios

How to Make Multiple Connection ID Scenario More Scalable

Until now we were fetching all connection ids for a user and invoking client method on all of these. This way, methods meant for Chat would be called upon frame for co create or notification as well, which eventually slows down the application with unnecessary processing.

To make it better, you can store the origin of connection id along with it. When invoking markonline(), you can send a string say “source” as a parameter. For example from the Co-Create frame as markonline(“cocreate”) and from Chat window  markonline(“chat”)  and from the master page markonline(“master”) ; this will make your table look like this:

username

connectionid

Source

User1 24b11640-XXXX-4069-XX96-8389223418ac cocreate
User1 eaa2de3d-f7df-46ce-XXXX-32bdfe612794 master
User2 8d2XXcc5-XX61-4f8d-a9f4-d3bcXXX1f14c cocreate
User2 3b900a78-4c1e-4XX8-be2c-XXXXXXXX chat
User3 XXXXXX-af57-4cc0-a2c0-4075947e3915 cocreate
User3 7f946c23-XXXX-4b49-b7d8-ee97cac5eXXX chat
User4 b2136fe5-XXXX-48d3-XXXX-047b77f34b09 master
…… …… ……

Now while fetching the list of connection ids from the table with isUserOnline(string username) method, you can specify source based on the method you are invoking it for by passing it as a where clause to the query. So when you want connection id for chat methods, you will fetch record only for source=”chat”.

How to Enhance Same Code for Multiple Sessions of Same User

Today a user can run the application from multiple devices as well. To make the above approach work for multiple session scenarios, you can store session id along with userid, source and connection id and fetch the result based on these parameters. This will ensure that when you invoke client method from the server, it reaches the destination it is meant to reach. Similarly, while deleting records when a user logs off or closes a browser window, you delete rows belonging to that session only.

Perspective

As I said earlier, SignalR and its usability looks very promising, and you saw how you can embed real time web in the application without getting your hands dirty. Yes, there are tricks, which you would have to play while working on selected list of connection ids however that is restricted to some “ifs” here and some “where” there but saves us from dealing with the rawness of communication APIs.

References

1. ASP.Net Forums. “How to manually set the connection id”.

Advertisements

§ 3 Responses to Real-Time Web Enablement with SignalR in .Net

  • streaming says:

    I really like reading through a post that will make people think.
    Also, thank you for allowing me to comment!

  • dvb t says:

    I’ve been browsing on-line more than 3 hours these days, yet I by no means discovered any attention-grabbing article like yours. Itˇ¦s beautiful value sufficient for me. In my opinion, if all site owners and bloggers made just right content as you did, the net can be a lot more helpful than ever before.

  • Odis Lloyd says:

    The primary function of SignalR is to allow real-time communication between server and client, but that’s not all that you can use the hubs for.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

What’s this?

You are currently reading Real-Time Web Enablement with SignalR in .Net at Naik Vinay.

meta

%d bloggers like this: