SignalR Connection Indicator reloaded

Some time ago I’ve written a blog post on how to build a connection indicator using ASP.Net MVC, SignalR and TypeScript. I had to write one again and did an improved version of the previous one by better using Knockout.js
.
The final result looks like the initial graphic. So the connection indicator will change its color and text to reflect the online state of the app.
It also uses a view-model that is bound using databinding to the DOM elements. So we are talking of a MVVM pattern here. As the basic principal still applies we can go straight to the code.
SignalR Hub
First of all I implemented a very simple SignalR Hub in C# using Visual Studio 2015 “Add new item” dialog:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Microsoft.AspNet.SignalR; namespace WebApplication1.Hubs { public class ConnectionStateHub : Hub { public void Hello() { Clients.All.hello(); } } }
Razor Layout
This time I’ve integrated the connection indicator in the Razor layout _Layout.cshtml
so its rendered on all my pages. The layout is a standard Bootstrap 3 page with Knockout.js loaded. The important part of code is this one:
<div class="navbar-header pull-left connectionStateNav"> <span id="connectionStateContainer" style="font-size:18px;" class="hidden"> <span class="label label-default"> <span></span> </span> </span></div>
Its basically a Bootstrap label with a span
inside it. I use just these two elements with databinding for Knockout.js. The outer label binds its CSS class to connectionStateCssClass
while the inner Span binds its text to text to connectionStateText
.
At the bottom of the _Layout.cshtml
I have my TypeScript (Javascript) linked:
http://~/signalr/hubs
My external script file gets initialized using the following Javascript code at the bottom of the _Layout.cshtml:
$(function () { window.connectionState = new MyApp.Core.OnlineStateViewModel(); ko.applyBindings(window.connectionState, $(".connectionStateNav").get(0)); window.connectionState.startSignalRHub($.connection); $("#connectionStateContainer").removeClass("hidden"); });
It loads my TypeScript code from MyAppOnlineState.js and the SignalR hub from the virtual reference signalr/hubs. Then it create a new instance of MyApp.Core.OnlineStateViewModel
and apply the Knockout databinding using the data-
attributes for all elements within my connection state DIV
. Finally the SignalR Hub gets started and the connection indicator shown by removing the hidden
class.
Viewmodel OnlineStateViewModel
Now you probably as for the MyAppOnlineState.js which is a TypeScript file so its source-code is in *MyAppOnlineState.ts. Here we go:
namespace MyApp.Core { export class OnlineStateViewModel { private connectionStateHub: any; private subscriptions: Array<Function> = []; public connectionState = ko.observable(4); public connectionStateText = ko.observable(""); public connectionStateCssClass = ko.observable("info"); public subscribeStateChange(callback: Function): void { this.subscriptions = this.subscriptions.concat(callback); } public startSignalRHub(connection: any) { this.connectionStateHub = connection.connectionStateHub; this.connectionStateHub.client.hello = () => { console.info("SignalrR: hello() received."); } connection.hub.stateChanged((state: any) => this.connectionStateChanged(state)); connection.hub.disconnected(() => { setTimeout(() => { connection.hub.start(); }, 10000); // Restart connection after 5 seconds. }); connection.hub.start(); } public connectionStateChanged(state: any): void { const stateConversion = { 0: "Verbinde", 1: "Online", 2: "Neu verbinden", 4: "Offline" }; const stateClass = { 0: "label-default", 1: "label-success", 2: "label-warning", 4: "label-danger" }; console.log("SignalR state changed from: " + stateConversion[state.oldState] + " to: " + stateConversion[state.newState]); this.connectionState(state.newState); this.connectionStateText(stateConversion[state.newState]); this.connectionStateCssClass("label " + stateClass[state.newState]); this.subscriptions.forEach(f => f(state)); } } }
The viewmodel basically sets things up in startSignalRHub
. Important here is the assignment of the eventhandler stateChanged
calls the connectionStateChanged()
function. This one calculates new values for the properties connectionState
, connectionStateText
and connectionStateCssClass
.
The viewmodel also features a subscriber mechanism where other scripts can add them so they get notified if a connection state change happens. They can do so by calling the function subscribeStateChange()
with the callback to call in case of the connection state changes.
Categories