I can think of two ways of achieving this objective,
A. Interval polling
This approach involves the client polling
the server for new data in preconfigured time interval.
The client displays the new data and waits
for the specified time and repeats the request again.
The drawback of this alternative is the unnecessary
requests that is wasted to continually check for new data- even if the new data
is available or not.
The conversation between the client (browser)
and the server goes along the line of
Client: “Do you have new Data?”
Server: “No”
Client waits for 5 seconds and tries again
Client: “Do you have new Data?”
Server: “yes”
Client will update the dashboard
However, instead of the client continually checking
the server for new data, Is there a way where the server can notify the client
when the new data is ready. Luckily yes. Here SignalR comes to the rescue.
B. SignalR
This library
allows us to write an application in which there is a bi-directional
communication between the server and the client. In the newest version of
browsers that support the new HTML5 API web sockets are used for communication.
In browser where web sockets are not supported
it will fallback to other legacy options to achieve the same objective. The
list of fallback options include long polling ,interval polling etc.
At the core of this implementation we have the Connection Hubs . Hubs provide a high level
RPC framework over PersistentConnection. All the notification from the server
to the client and vice versa is done through the hub. When the application is
run, SignalR will emit the javascript equivalent of the Hub you defined in your
C# assembly. So that you can start a connection from the client and then call
methods defined in the hub(Server Calls). Moreover you can add client call in
your javascript file that can be called by the server methods for server to
client communication.
The SignalR documentation can be found here
The SignalR Nuget package installation procedure can be found here
Lets see some code …
1.
Install Nuget
package . In this example I am hosting the hub inside asp.net mvc app.
2.
Register the
routing for signalr hub to be accessed through URL . Note: the signalr route
registration should come before the asp.net mvc route registration.
If you don’t specify an
alternative path name. The default /signalr/hubs will be used
protected void
Application_Start()
{
RouteTable.Routes.MapHubs();
RegisterRoutes(RouteTable.Routes);
}
3.
Server Code : I
created a hub class called ReportHub. All Hub classes should inherit from the
base Hub Class.
The ReportHub class now will have access to the public
properties defined in the HubClass
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
Microsoft.AspNet.SignalR.Hubs;
namespace
SignalRDemo
{
public class ReportHub : Hub
{
public
void NotifyClients()
{
//notify
all other clients to update their data
Clients.Others.updateReport1();
Clients.Others.updateReport2();
}
public void BroadCastData1Available()
{
Clients.Others.updateReport1();
}
public void BroadCastData2Available()
{
Clients.Others.updateReport2();
}
}
}
The ReportHub has three server calls that can be
invoked by clients.
Looking NotifyClients()
in detail
In this
line of code Clients.Others.updateReport1();
updateReport1 is a method defined in the client.
I am sending out the notification to all
clients except for the one who made the server call. If you want the notifier itself to be notified too, You can use
Clients.All instead of Clients.Others. Note updateReport1() is a method defined
in the client. Upon notification the client will execute the updateReport1()
method in the javascript.
Some notable properties of Hub.
a.
Clients - list of clients connected to the hub. This
property will give you access to
Clients.All – all clients
Clients.Others – all clients except the one calling
the hub’s method
Clients.Caller – the called calling hub method.
b.
Context
c.
Groups
4.
Client Code :
Register the following
scripts on your client/view
<script src="/Scripts/jquery.signalR-1.0.0-rc1.min.js"
type="text/javascript"></script>
<script src="@Url.Content("~/signalr/hubs")"
type="text/javascript"></script>
"~/signalr/hubs” – this is the path defined on your route. When the application is run, the signalR assemblies will use reflection to emit the javascript equivalent of the ReportHub class defined in the assembly.
The
hub can be accessed from the client as show below. The connections can be
started and an optional call back can be invoked when the connection is started
or done.
You
can also define methods on the clients to be invoked by the server. The updateReport()
method discussed in the above section (Server Code) is define as follows.
// Declare a function on the myHub hub so the server
can invoke it
rptHub.client.updateReport1 = function
() {
// do something
};
The
whole script of the client is shown below.
$(function () {
// Proxy created on the fly
var rptHub = $.connection.reportHub;
// Declare a function on the rptHub hub so the server
can invoke it
rptHub.client.updateReport1 = function
() {
RefreshData('map_canvas');
};
rptHub.client.updateReport2 = function
() {
RefreshData('map_canvas2');
};
// Start the connection
$.connection.hub.start().done(function
() {
});
});
How can
we call the server from the client?You will call the server property of the hub and then
you will have access to all the public methods in the hub.
E.g. If you want to invoke the notifyClients() method
defined in the server/hub.
// Call the notifyClients method on the server
rptHub.server.notifyClients();
Putting it all together
I
have included a demo asp.net mvc application hosting a signalR hub. The
application has a dashboard page which has two geomap charts and there is an admin page with three
buttons. Clicking the buttons on the admin page will notify the charts on the
dashboard to update their content with a new data. The demo shows the
bi-directional communication from the client to the server and vice versa.
Admin page to Server Hub => client to
server
Server
Hub to Dashboard page => server to client
The full demo can be downloaded from here