How to write real-time web app using SignalR, TypeScript, KnockoutJS, HTML5?

Nowadays, end-users like responsive applications and there are times when certain type of applications need to support real-time updates if required. In this post, I’ll tell you how to write real-time web app using SignalR, TypeScript, KnockoutJS, HTML5.

As such this is a how-to post, I expect readers to have some basic knowledge about these technologies mentioned above. But in a nutshell:

What is SignalR?

ASP.NET SignalR is a new library for ASP.NET developers that makes developing real-time web functionality easy. SignalR allows bi-directional communication between server and client. Servers can now push content to connected clients instantly as it becomes available. SignalR supports Web Sockets, and falls back to other compatible techniques for older browsers. SignalR includes APIs for connection management (for instance, connect and disconnect events), grouping connections, and authorization.
ASP.NET

What is TypeScript?

Typescript is a typed superset of JavaScript that compiles to plain JavaScript. It runs in any browser, any host and any OS. It is open source with good tooling support for various IDE and code editors.
– Learn more about it here.

What is KnockoutJS?

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model. Any time you have sections of UI that update dynamically (e.g., changing depending on the user’s actions or when an external data source changes), KO can help you implement it more simply and maintainably.
KnockoutJS

Requirement/Scope

A real-time web application can be really exciting and SignalR makes it more interesting by providing strong client support as it can leverage Web Sockets, Server-Sent Events (SSE), Forever Frame and Long Polling whenever needed.

Let us define the scope of the real-time application that will be ready by the end of this post. There is a requirement to show the CPU, paging and disk usage on the server to the users of our web application. This can be part of an internet or intranet web app. The code snippets in this post doesn’t account authentication or authorization to keep the scope simple. Ideally, this kind of information can be a part of app’s dashboard.

Tools/Packages

I’m using Visual Studio for this requirement to create an ASP.NET web application with MVC & Web API and name it as  “PerfSurf”. I opted this template type so as to get Bootstrap, jQuery and some other default packages. Make sure you have proper TypeScript support in your IDE with latest Web Essentials update.

Use the Nuget Package Manager to install following packages: KnockoutJS, SignalR and their nuget packages names are knockoutjs, Microsoft.AspNet.SignalR respectively.

To show the real-time updates on the user-interface get Smoothie.js, a charting library. Unfortunately, this is not available via nuget at the time of writing this post. So, visit the link, copy the raw library code and paste it in a new file in your vendor specific scripts folder.

To leverage strong typing support of TypeScript, install following packages: jquery.TypeScript.DefinitelyTyped, knockout.TypeScript.DefinitelyTyped, signalr.TypeScript.DefinitelyTyped, smoothie.TypeScript.DefinitelyTyped. These are the definition files that helps an IDE to give proper intellisense support.

Server-side Setup

Based on your authentication type – Internet or Intranet, you may or may not have a Startup.cs file in your project at root level. If it is not there, add this file and configure the app to use SignalR. My project is internet type so I already had this file and it looks like this:

The method named MapSignalR maps SignalR hubs to the app builder pipeline at /signalr.

Hub

The next main step is to create a custom Hub that derives from Microsoft.AspNet.SignalR.Hub. It provides methods that communicate with SignalR connections that is connected to a hub. This hub will basically define all the methods (marked public) that clients (browser) can use. Below is the code to create a hub for our requirement:

The code statement Clients.All.NewCounters(results); instructs SignalR to invoke a JavaScript function named newCounters() on every connected client and pass results object as parameter to it. The All member is a dynamic object which allow us to add any name. In the later version of SignalR, a new feature was added which allows a custom Hub to inherit from the base hub of specific type where all the members defined in this type is supposed to be implemented in JavaScript/client code.

So, defining a IPerfHubClient interface also provides us intellisense support in IDE otherwise there will be no support as All is a dynamic type. It’s definition is shown below:

HubMethodName attribute on member instructs SignalR to convert pascal-case to camel-case when it creates the client-side methods on the fly for consumption. This is handy as writing a method name in camel-case on server-side doesn’t look right!

Let us look at StartCounterCollection implementation. We want our hub to start sending the counter values as soon as possible. So, we just start a new task which runs a while loop but with some delay. It consumes a custom counter service named PerfCounterService to get the results of CPU, Paging and Disk usage of server which is then sent to all the connected client using Clients.All.NewCounters(results). Note that we also instruct that this task is a long-running task with the help of TaskCreationOptions.

PerfCounterService is a simple class that just setups the counters that the client needs as per the requirement of our application. It is good to keep this separate so that this counters can be added or removed as and when required without affecting the rest of the application. The definition of this class is as follows:

It stores a list of counters to be used in app and GetResults method just returns a friendly name and a value for counter. It uses a custom counter wrapper type  – the definition is mentioned below:

The above class is a wrapper for System.Diagnostics.PerformanceCounter to define a friendly name, category, counter, instance for a counter. Note that all counter have different values for category, counter or instance. Look at the PerfCounterService to check what is required for different required counters.

As such this project is using ASP.NET MVC, we will next modify the Home/Index.cshtml view to have following code:

Code from line 5-10 uses Knockout’s foreach binding to render the structure for all the counters defined in the model. We have 3 counters as per requirement. It then creates a canvas element for each counter with a unique id using counter’s name. This makes sure that our app is ready to support any number of counters sent from the server. Also this canvas is required to use Smoothie chart library so that it can stream data on it.

Next is the scripts section in the view. First, all the third-party scripts are references. The important one is on-line 15 – which doesn’t exist physically but when a request goes to ~/SignalR/hubs then server responds with all the JavaScript code that it creates on the fly by going through all the hubs and its public methods to the browser.

Client-side Setup

Next we reference our custom JavaScript files.

ChartEntry.ts file is created to define a ChartEntry class internally uses SmoothieChart which defines a chart for a counter. SmoothieChart has a timeSeries which it uses to track a value at particular time. Instead of matching server & client time, we just use client-side time to append a counter’s value. The implementation of this type looks like this below:

Next, we define a ViewModel class in ViewModel.ts file that acts as a state for current view. This basically uses KnockoutJS for data-binding and looks like:

It is quite a simple class with counters member as an array that will hold all the counter values. As discussed above, the friendly name of every counter is used to identify whether the counter already exists or not. If it doesn’t exist then a new chart-entry is created and added to the counters array. And eventually, the value is added to the entry irrespective of whether entry is new or old.

The important bit is still remaining to glue SignalR work done on server with client-side setup. Add app.ts file that looks like snippet below:

If you use the code above in your project, you will see compile time errors for perfHub. TypeScript compiler isn’t happy as it can’t find any matching definition for it. To solve this, use Hubs.tt – a T4 Template that goes through all the registered Hubs and creates a typescript definition to be used from other typescript files. Paste this template file inside Scripts folder so that the references for SignalR and jQuery in the template matches with your physical files. Also, update line number 4 to match your version of SignalR.

If everything goes well, the compile time errors wherever perfHub is used will be solved. Not the method newCounters is camel-case as instructed in the server code above. When server instructs to call this method, client code then internally calls addCounters  function defined in ViewModel class. Read the comments in the code above to see what each statement is doing to fulfil the requirements of our real-time web app.

If you have followed all the instructions in this post, you will now have a working real-time web application which will look like this:

Real-time web app showing Process, Paging and Disk of a server: write real-time web app using SignalR, TypeScript, KnockoutJS, HTML5

Real-time web app showing Process, Paging and Disk usage of a server.

This will work well on IIS Express on your local machine but make sure to enable Web Sockets for IIS if you are using IIS 8 and above as by default it is turned off.

This sums up this post to write real-time web app using SignalR, TypeScript, KnockoutJS, HTML5. If you face any issues, let me know and I’ll try to help you. This just scratches the surface and there are many other great real-time usages that can be achieved using SignalR.

Siddharth Pandey

Siddharth Pandey is a Software Engineer with thorough hands-on commercial experience & exposure to building enterprise applications using Agile methodologies. Siddharth specializes in building, managing on-premise, cloud based real-time standard, single page web applications (SPAs). He has successfully delivered applications in health-care, finance, insurance, e-commerce sectors for major brands in the UK. Other than programming, he also has experience of managing teams, trainer, actively contributing to the IT community by sharing his knowledge using Stack Overflow, personal website & video tutorials.

You may also like...

Advertisment ad adsense adlogger