Tuesday, 11 October 2016

Getting started with SignalR

Follows on from previous post: Real-time SignalR and Angular 2 dashboard

I had a couple of questions from someone who forked the project on GitHub and is using it as the basis for their own custom dashboard, which reminded me that there are a few key things I picked up on my learning journey that I should share. These are primarily focused around SignalR aspects.

An instance of a SignalR hub is created for each request

A single instance is not shared across all clients connected to that hub. This is much like a controller in ASP.NET MVC, whereby a new instance of the controller is created for each request. Hence in my SignalRDashboard project, the mechanism for holding a single instance of shared data for all connections, is via a singleton instance that gets passed into each hub's constructor.

Setup callback methods in Javascript for SignalR hubs BEFORE starting the SignalR connection

To open a SignalR connection, you use the following:
    $.connection.hub.start();
To be able to receive messages from the server-side SignalR hub in client-side Javascript, you have to hookup a method to be called. You'd do this using something like:
    var hub = $.connection.myDemoHub;
    hub.client.updateMeWhenYouHaveUpdates = function(message) {
        // Do something useful with what we've just received from the server
    };
The import thing to remember is once you've started the SignalR connection, you can't hook up these callbacks. So make sure they are done BEFORE you start the connection. The correct ordering would be:
    var hub = $.connection.myDemoHub;
    hub.client.updateMeWhenYouHaveUpdates = function(message) {
        // Do something useful with what we've just received from the server
    };
    $.connection.hub.start();

You can connect to multiple SignalR hubs over the same connection

This is great as it means, you can connect to multiple hubs easily - all you need to do is setup the callback methods in Javascript before you open the connection, as per the previous point.
    var hub1 = $.connection.myDemoHub;
    hub1.client.updateMeWhenYouHaveUpdates = function(message) {
        // Do something useful with what we've just received from the server
    };

    var hub2 = $.connection.myOtherHub;
    hub2.client.callMePlease = function(message) {
        // Do something useful with what we've just received from the server
    };
    $.connection.hub.start();
In the SignalRDashboard project, you'll see this being handled in dashboard.js as follows:
  • each Angular 2 dashboard component registers itself with dashboard.js when it is constructed
  • once the component has been initialised (ngOnInit event), it lets dashboard.js know that it's finished and registration is completed
  • once all components have completed registration, then the initialiseComponents() method is called which then calls in to each registered component (each must expose a setupHub() method) so they can set up the callbacks they're interested in from the hubs they use
  • finally, the connection is then started

The basics are covered well in the official SignalR site, but the points above were some of the main things that I found myself looking a bit deeper for.

Friday, 7 October 2016

Real-time SignalR and Angular 2 dashboard

tl;dr Check out my new SignalRDashboard GitHub repo
Followup post: Getting started with SignalR

For a while now, I've had that burning curiosity to do more than just the bit of hacking around with SignalR that I'd previously done. I wanted to actually start building something with it. If you're not familiar with it, SignalR is a:

...library for ASP.NET developers that makes developing real-time web functionality easy.

It provides a simple way to have two-way communication between the client and server; the server can push updates/data to any connected client. There are a number of great starting examples out there, but to give a very quick overview, a typical basic example is web-based chat functionality. When a user navigates to the chat page using their browser-of-choice, a connection is made to a SignalR "hub" on the server, using Javascript. This connection provides the channel for bi-directional client-server communication. When a user enters some text in the UI and presses send, a message is sent across this channel to the server, invoking a method on the hub. In the case of a basic chat example, this then broadcasts the message out to all the clients who are connected to that hub, which results in a Javascript method on the client being called to then render that message out to each user's screen.

No need to make AJAX requests to send requests to the server. No need to make AJAX requests to make polling-style requests to the server for updates. SignalR handles the approach used to maintain the communication channel between the client browser and the server, depending on the functionality supported by the browser. It also handles the nuts and bolts of how to broadcast out to any connected clients.

Enter the dashboard

In the dev room I work in, we've had a large screen showing a dashboard of metrics for years - evolving over time as we realise the value of new metrics. I decided that a great learning project to work on in my spare time would be to create a real-time web-based replacement (the original one was a WPF app). I'm a big fan of giving visibility of relevant and timely, high-level application metrics to the business. Current CI build broken? Show it. Recent system error rates? Show it. How many stories do the test team have left to accept? Show it. That ability to take a quick glance, and get a quick feel for the current state of play across a wide area of the business, is invaluable. It's also handy to have things flash and/or play a sound, when there's something of particular importance to flag up.

From a technical perspective, I set myself a number of goals I wanted to achieve:

  • a centralised dashboard accessible across all areas of the business (it's an ASP.NET MVC 5 web app...job done!)
  • no matter how many clients are connected to the dashboard, I don't want to increase the load on the systems/services that the dashboard is drawing data from
  • try out a new (to me) Javascript framework to aid the creation of slick, dynamic views
  • create an dashboard framework that's easy to extend, with some demo dashboard components so hopefully others interested in the technology can find it useful, and better still, put it to use in their own environments

Moar learning!

AngularJS has also been on my radar for a while, and with Angular 2 coming along as the successor to Angular 1, it seemed like a chance to have a play around with that too. When I first started hacking about with it, an early beta version was available which I started off using. More recently, the Final Release has become available - so I have since upgraded to that, patching up where there were breaking changes.

GitHub repo

The result is a cunningly named (does-what-it-says-on-the-tin) SignalRDashboard project GitHub repo. There's a few demo components as examples, and I plan to add to those as and when I have time. It is still very much work in progress and evolving!

Here's a quick screenshot with some of the demo components currently written (all randomly generated data, refreshing every 15 seconds):

As always, all feedback is welcome - if you do find it useful/end up using it, drop me a message as it would be great to know!