Have you ever encounter a system requirement that require you to create a web page that needs to be consistently updated in real time? For example, a stock market watcher. As we know, stock prices are changing from time to time during the trading period. How can we create an efficient web page which able to show the latest price quickly and real time without requiring user to keep clicking a refresh button? I would like to introduce ASP.NET SignalR to solve the problem.
So, notice my stockHubProxy.client.refresh method? This method later will be used in the server code to trigger the Javascript to refresh the data in my grid view. The code below is how I trigger all the clients refresh their UI from server.
One awesome thing about SignalR is the stock object that I passed to hub clients with the above C# code. I do not need to manually serialize the C# object into something like JSON or XML, I am able to get the object with value directly and use it in Javascript.
That's it! Amazingly it is easy to use SignalR. In order to verify it is working as expected, I open up 2 browsers, one is IE11 and another is Chrome 33+. I updated one of the value from IE, then the value change immediately in the Chrome.
For a quick start, this is the simplest SignalR implementation that I have done with one way from server trigger clients to perform some action. It also support the other way, from client trigger server to execute some methods or logic. You can explore further for more complicated implementation base on the API documents and sample that you can find here.
If you are interested with my complete source code, feel free to download it from here.
Concept
My stock market watcher has 1 page only. The page allow user to view and update stock prices. Users open the Default.aspx page to view the stock prices. One of the users update the data. The service will trigger the SignalR hub to ask all the clients to refresh their own UI.
So, instead of using polling strategy by having every individual client to refresh their UI in a timely interval. They get triggered to refresh their UI when there is data change and necessary.
So, before the browser can receive the signal from SignalR hub, it needs to be registered with the SignalR hub first. The registration will create a web socket connection between browser and the server. And that, SignalR require a web socket supported browser to best work with such as IE10+. However, it still actually works with older version of browser. check out the list of supported platforms.So, instead of using polling strategy by having every individual client to refresh their UI in a timely interval. They get triggered to refresh their UI when there is data change and necessary.
Implementation
I will skip some of the basic details like creating ASP.NET web application project and creating the two web pages and UI design, and straight to the point where how to get SignalR works.
First, nuget the SignalR component library or visit the SignalR site to download it manually.
Now, code your web application to start initializing the SignalR hub with the following code:
[assembly: OwinStartup(typeof(StockSample.UI.Web.Hubs.Startup))]
namespace StockSample.UI.Web.Hubs
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
hubConfiguration.EnableJavaScriptProxies = true;
app.MapSignalR("/signalr",
hubConfiguration);
}
}
}
In my Default.aspx, I have a grid view and it support edit function. Once I am done designing my UI and ensure the app is functioning, I add the following Javascript references:
<script src="Scripts/jquery-1.6.4.min.js"></script>
<script src="Scripts/jquery.signalR-2.0.2.min.js"></script>
<script src='<%: ResolveClientUrl("~/signalr/hubs") %>'></script>
Then, code the following to let the browser register itself with the hub during page load:
<script type="text/javascript">
//Get
the hub proxy, this is autogenerated during SignalR startup
var stockHubProxy = $.connection.stockHub;
//The
refresh method is to let server to trigger
stockHubProxy.client.refresh = function (stock) {
//Just
some tracing purposes
console.log('Refresh method triggered successfully!');
console.log(stock);
//Refresh
the gridview with latest data
$("#stocksGrid
tr").each(function (i) {
if ($(this)[0].id == stock.ID) {
$(this).find('td:eq(1)').text(stock.Symbol);
$(this).find('td:eq(2)').text(stock.Company);
$(this).find('td:eq(3)').text(stock.Last);
$(this).find('td:eq(4)').text(stock.Min);
$(this).find('td:eq(5)').text(stock.Max);
$(this).find('td:eq(6)').text(stock.Change);
$(this).find('td:eq(7)').text(stock.Volume);
//highlight
the row that has data changed then slowly fade
$(this).attr('style', 'background-color: yellow;');
$(this).animate({ backgroundColor: 'white'}, 3000);
}
});
};
//This
event fire when the hub has started
$.connection.hub.start().done(function () {
//Just
to trace whether your browser successfully connected to SignalR hub
console.log('Connected to SignalR hub, connection ID = ' + $.connection.hub.id);
})
</script>
//Trigger
hub
var context = GlobalHost.ConnectionManager.GetHubContext<StockHub>();
context.Clients.All.refresh(stock);
One awesome thing about SignalR is the stock object that I passed to hub clients with the above C# code. I do not need to manually serialize the C# object into something like JSON or XML, I am able to get the object with value directly and use it in Javascript.
That's it! Amazingly it is easy to use SignalR. In order to verify it is working as expected, I open up 2 browsers, one is IE11 and another is Chrome 33+. I updated one of the value from IE, then the value change immediately in the Chrome.
Summary
Surprisingly SignalR is easy to implement. If you want to have a web page which is able to real time always showing the latest data, what would you do? Web application is always stateless, no way to keep data in memory and display it like a windows form application. I suppose what most people would do is to create a Javascript timer which call a web service in a timely interval to check for any data change. So, which do you think is more efficient? Having a always alive web socket connection or every 3 seconds call a web service with Javascript?For a quick start, this is the simplest SignalR implementation that I have done with one way from server trigger clients to perform some action. It also support the other way, from client trigger server to execute some methods or logic. You can explore further for more complicated implementation base on the API documents and sample that you can find here.
If you are interested with my complete source code, feel free to download it from here.