Real Time Chart Using SignalR and Chart.js

This article is a walkthrough of creating a web application that displays a chart that is updated in real time.

An Introduction

This article is a walkthrough of creating a web application that displays a chart that is updated in real time. Using SignalR, the Chart data is kept synchronised throughout the connected clients. Chart data is sent from the Server to all the clients so that the Chart is displayed exactly similar to all.

For this demo I have added one Line Chart and one Pie Chart.

Tools Used
  • Visual Studio 2012
  • SignalR
  • Chart.js

About SignalR

SignalR is a server-side software system designed for writing scalable internet applications, notably web servers. Programs are written on the server side in C#, using event-driven, asynchronous I/O to minimize overhead and maximize scalability.

About Chart.js

Chart.js is a free chart tool available for a HTML5 browser with nice visualization and animation.

Read more about Chart.js here :

Download Chart.js from the preceding link.

Getting Started

Step 1

Creating a new web project in Visual Studio. I am using Visual Studio 2012.



Step 2

Getting the Chart.js (download from the preceding link).

Add the Chart.js into the Scripts folder.



Step 3

Installing the SignalR.

Click Tools then select Nuget Package Manager > Package Manager Console then type "install-package Microsoft.AspNet.SignalR".


Step 4

   - 4.1 Create the Chart Broadcaster Class. I have included all other required classes in this class only.

Right-click the Project folder then select Add > Class.. then type the class name as ChartDataUpdate.cs.

  1. using System;    
  2. using System.Collections.Concurrent;    
  3. using System.Collections.Generic;    
  4. using System.Threading;    
  5. using Microsoft.AspNet.SignalR;    
  6. using Microsoft.AspNet.SignalR.Hubs;    
  7. using Newtonsoft.Json;    
  8.     
  9. namespace RealTimeChart    
  10. {    
  11.     //Other class will be added here  
  12.   
  13.     public class ChartDataUpdate    
  14.     {    
  15.     }    
  16. }    
   - 4.2 Add the RandamNumberGenerator class in ChartDataUpdate.cs. This class generates a Random Number for the Chart Data.
  1. public class RandomNumberGenerator    
  2. {    
  3.     static Random rnd1 = new Random();    
  4.     static public int randomScalingFactor()    
  5.     {    
  6.   
  7.         return rnd1.Next(100);    
  8.     }    
  9.     static public int randomColorFactor()    
  10.     {    
  11.   
  12.         return rnd1.Next(255);    
  13.     }    
  14. }    
   - 4.3 Add the LineChart class to ChartDataUpdate.cs. This class has the two properties, lineChartData and colorString. lineChartData is being set with ramdom numbers and color string with random color. I have fixed the Line Chart data to 7 points.
  1. //The Line Chart Class    
  2. public class LineChart    
  3. {    
  4.     [JsonProperty("lineChartData")]    
  5.     private int[] lineChartData;    
  6.     [JsonProperty("colorString")]    
  7.     private string colorString;    
  8.   
  9.     public void SetLineChartData()    
  10.     {    
  11.         lineChartData = new int[7];    
  12.         lineChartData[0] = RandomNumberGenerator.randomScalingFactor();    
  13.         lineChartData[1] = RandomNumberGenerator.randomScalingFactor();    
  14.         lineChartData[2] = RandomNumberGenerator.randomScalingFactor();    
  15.         lineChartData[3] = RandomNumberGenerator.randomScalingFactor();    
  16.         lineChartData[4] = RandomNumberGenerator.randomScalingFactor();    
  17.         lineChartData[5] = RandomNumberGenerator.randomScalingFactor();    
  18.         lineChartData[6] = RandomNumberGenerator.randomScalingFactor();    
  19.   
  20.         colorString = "rgba(" + RandomNumberGenerator.randomColorFactor() + "," + RandomNumberGenerator.randomColorFactor() + "," + RandomNumberGenerator.randomColorFactor() + ",.3)";    
  21.     }          
  22. }    

   - 4.4 Add the PieChart class to the ChartDataUpdate.cs. This class has one property named "value". For this demo purpose I have taken only 3 values that will create 3 pie chart slices. The data is populated randomly.

  1. //The Pie Chart Class    
  2. public class PieChart    
  3. {    
  4.     [JsonProperty("value")]    
  5.     private int[] pieChartData;    
  6.   
  7.     public void SetPieChartData()    
  8.     {    
  9.         pieChartData = new int[3];    
  10.         pieChartData[0] = RandomNumberGenerator.randomScalingFactor();    
  11.         pieChartData[1] = RandomNumberGenerator.randomScalingFactor();    
  12.         pieChartData[2] = RandomNumberGenerator.randomScalingFactor();    
  13.   
  14.     }    
  15.   
  16. }    
4.5 Finally update the main ChartDataUpdate class. This class holds the Timer ChartTimerCallBack and method SendChartData that will be called by the Hub Class to send data to the client.
  • Creates a Singleton Instance of this class
  • Creates a Timer that runs the method ChartTimerCallBack every 5 seconds
  • ChartTimerCallBack is a method that calls SendChartData that sets random data for the Line (SetLineChartData) and Pie (SetPieChartData) Chart and calls the client method UpdateChart
  • Do note that the client method defined in the server class is in Title Case but when using it in the client JavaScript method it will be with camelCase. So UpdateChart will be refered to as updateChart in JavaScript.
  1. public class ChartDataUpdate    
  2. {    
  3.   
  4.     // Singleton instance    
  5.     private readonly static Lazy<ChartDataUpdate> _instance = new Lazy<ChartDataUpdate>(() => new ChartDataUpdate());            
  6.     // Send Data every 5 seconds    
  7.     readonly int _updateInterval = 5000;       
  8.     //Timer Class    
  9.     private Timer _timer;    
  10.     private volatile bool _sendingChartData = false;    
  11.     private readonly object _chartUpateLock = new object();    
  12.     LineChart lineChart = new LineChart();    
  13.     PieChart pieChart = new PieChart();    
  14.   
  15.     private ChartDataUpdate()    
  16.     {    
  17.   
  18.     }    
  19.   
  20.     public static ChartDataUpdate Instance    
  21.     {    
  22.         get    
  23.         {    
  24.             return _instance.Value;    
  25.         }    
  26.     }    
  27.         
  28.     // Calling this method starts the Timer    
  29.     public void GetChartData()    
  30.     {                
  31.         _timer = new Timer(ChartTimerCallBack, null, _updateInterval, _updateInterval);    
  32.             
  33.     }    
  34.     private void ChartTimerCallBack(object state)    
  35.     {                
  36.         if (_sendingChartData)    
  37.         {    
  38.             return;    
  39.         }    
  40.         lock (_chartUpateLock)    
  41.         {    
  42.             if (!_sendingChartData)    
  43.             {    
  44.                 _sendingChartData = true;                        
  45.                 SendChartData();    
  46.                 _sendingChartData = false;    
  47.             }    
  48.         }    
  49.     }    
  50.   
  51.     private void SendChartData()    
  52.     {    
  53.         lineChart.SetLineChartData();    
  54.         pieChart.SetPieChartData();    
  55.         GetAllClients().All.UpdateChart(lineChart,pieChart);     
  56.   
  57.     }    
  58.   
  59.     private static dynamic GetAllClients()    
  60.     {    
  61.         return GlobalHost.ConnectionManager.GetHubContext<ChartHub>().Clients;    
  62.     }    
  63.   
  64. }    
Step 5

Create the Chart Hub Class.

Right-click the Project folder then seelct Add > Class.. then type the class name as ChartHub.cs.

  1. using System;    
  2. using System.Collections.Generic;    
  3. using System.Linq;    
  4. using System.Web;    
  5. using Microsoft.AspNet.SignalR;    
  6.     
  7. namespace RealTimeChart    
  8. {    
  9.         
  10.     public class ChartHub : Hub    
  11.     {    
  12.        // Create the instance of ChartDataUpdate    
  13.         private readonly ChartDataUpdate _ChartInstance;    
  14.         public ChartHub() : this(ChartDataUpdate.Instance) { }    
  15.     
  16.         public ChartHub(ChartDataUpdate ChartInstance)    
  17.         {    
  18.             _ChartInstance = ChartInstance;    
  19.         }    
  20.      
  21.         public void InitChartData()    
  22.         {    
  23.             //Show Chart initially when InitChartData called first time    
  24.             LineChart lineChart = new LineChart();    
  25.             PieChart pieChart = new PieChart();    
  26.             lineChart.SetLineChartData();    
  27.             pieChart.SetPieChartData();    
  28.             Clients.All.UpdateChart(lineChart,pieChart);                
  29.    
  30.     
  31.             //Call GetChartData to send Chart data every 5 seconds    
  32.             _ChartInstance.GetChartData();    
  33.                 
  34.         }       
  35.          
  36.     }    
  37. }    
Step 6

Create the OWIN Startup Class.

Right-click the Project folder then seelct Add > Class.. then type the class name as Startup.cs.

  1. using System;    
  2. using Microsoft.Owin;    
  3. using Owin;    
  4. [assembly: OwinStartup(typeof(RealTimeChart.Startup))]    
  5. namespace RealTimeChart    
  6. {    
  7.     public class Startup    
  8.     {    
  9.         public void Configuration(IAppBuilder app)    
  10.         {    
  11.             // Any connection or hub wire up and configuration should go here    
  12.             app.MapSignalR();    
  13.         }    
  14.     }    
  15. }    
Step 7

Create the Startup aspx page. I have used the default.aspx page.

First add a reference to jQuery and Chart.js as in the following:

  1. <script src="Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>   
  2. <script src="Scripts/Chart.min.js" type="text/javascript"></script>  

Then add a reference to the required SignalR JavaScript files as in the following:

  1. <script src="Scripts/jquery-ui-1.8.20.min.js"></script>   
  2. <script src="Scripts/jquery.signalR-2.2.0.min.js"></script>   
  3. <script src="/signalr/hubs"></script>  

Add a Canvas area where the Line and Pie charts will be displayed as in the following:

  1. <table style="width: 100%">           
  2.         <tr>    
  3.             <td style="width: 50%; text-align: center">    
  4.                 <canvas id="canvasForLineChart" height="200" width="400">Chart is Loading...</canvas>    
  5.     
  6.             </td>    
  7.             <td style="width: 50%; text-align: center">    
  8.                 <canvas id="canvasForPieChart" height="200" width="400">Chart is Loading...</canvas>    
  9.             </td>    
  10.         </tr>     
  11. </table>    
Add a script to create a connection hub. When the connection is done then call the server the initChartData method. The updateChart method is called back from the server to update the chart data.
  1. <script>    
  2.     function checkHTML5() {    
  3.         var canvasForLineChart = document.getElementById("canvasForLineChart");    
  4.         if (canvasForLineChart == null || canvasForLineChart == "") {    
  5.             document.write("Browser doesn't support HTML5 2D Context");    
  6.             return false;    
  7.         }    
  8.         if (canvasForLineChart.getContext) {    
  9.     
  10.         }    
  11.         else {    
  12.             document.write("Browser doesn't support HTML5 2D Context");    
  13.             return false;    
  14.         }    
  15.     }    
  16.     
  17.     $(function () {    
  18.         //If not HTML5 Support the Exit    
  19.         if (checkHTML5() == falsereturn;    
  20.     
  21.         //Create the Hub    
  22.         var chartHub = $.connection.chartHub;    
  23.             
  24.     
  25.         //Call InitChartData     
  26.         $.connection.hub.start().done(function () {                
  27.             chartHub.server.initChartData();    
  28.                 
  29.         });    
  30.     
  31.         //Call to Update LineChart from Server    
  32.         chartHub.client.updateChart = function (line_data,pie_data) {    
  33.             UpdateLineChart(line_data);  //Call the LineChart Update method    
  34.             UpdatePieChart(pie_data);     //Call the PieChart Update method    
  35.         };    
  36.     
  37.           
  38.     });    
  39. </script>    
Create a script to create the Line and Pie Charts. I am creating both charts with the minimum required properties.
The UpdatePieChart and UpdateLineChart methods are used to update and recreate both the charts.
  1. <script type="text/javascript">    
  2.        ////////////////////////////////////////////////////////////////////////////////////////////////////////    
  3.        //Line Chart JSON Config (Line Chart Has fixed 1 data series here)    
  4.        var lineChartData = {    
  5.            labels: ["January""February""March""April""May""June""July"],    
  6.            datasets: [    
  7.             {                       
  8.                 fillColor: "",    
  9.                 data: [0]    
  10.             }    
  11.            ]    
  12.     
  13.        }    
  14.     
  15.        //Pie Chart JSON Config (Pie Chart Has fixed 3 Values/Slices here)    
  16.        var pieChartdata = [    
  17.                     {    
  18.                         value: 0,    
  19.                         color: "#F7464A",                            
  20.                         label: "East"    
  21.                     },    
  22.                     {    
  23.                         value: 0,    
  24.                         color: "#46BFBD",                             
  25.                         label: "West"    
  26.                     },    
  27.                     {    
  28.                         value: 0,    
  29.                         color: "#FDB45C",                             
  30.                         label: "North"    
  31.                     },    
  32.                     {    
  33.                         value: 0,    
  34.                         color: "#FE94DC",                            
  35.                         label: "South"    
  36.                     }    
  37.        ]    
  38.     
  39.        ////////////////////////////////////////////////////////////////////////////////////////////////////////    
  40.           
  41.        //PieChart Update method    
  42.        function UpdatePieChart(data) {    
  43.            //Set data returned from Server                
  44.            pieChartdata[0].value = data.value[0];    
  45.            pieChartdata[1].value = data.value[1];    
  46.            pieChartdata[2].value = data.value[2];    
  47.            //Update the Line Chart    
  48.            var canvasForPieChart = document.getElementById("canvasForPieChart");    
  49.            var context2DPie = canvasForPieChart.getContext("2d");    
  50.            new Chart(context2DPie).Pie(pieChartdata);    
  51.     
  52.        }    
  53.     
  54.        //LineChart Update method    
  55.        function UpdateLineChart(data) {    
  56.            //Set data returned from Server    
  57.            lineChartData.datasets[0].fillColor = data.colorString;    
  58.            lineChartData.datasets[0].data = data.lineChartData;    
  59.            //Update the Pie Chart    
  60.            var canvasForLineChart = document.getElementById("canvasForLineChart");    
  61.            var context2DLine = canvasForLineChart.getContext("2d");    
  62.            new Chart(context2DLine).Line(lineChartData);    
  63.        }    
  64.     
  65. </script>  

The full version of ChartDataUpdate.cs, ChartHub.cs and Default.aspx can be found in the download source.

Step 8

Build and Run. To test, open multiple HTML5 compatible browsers.

The Output



Limitations

  • In Firefox the Pie chart is not rendering properly.
  • I tested in Chrome only.
Link to my other SignalR Article "Simple Drawing in SignalR Using Visual Studio 2012" .

Have a nice Day. :-)