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

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. namespace RealTimeChart
  9. {
  10. //Other class will be added here
  11. public class ChartDataUpdate
  12. {
  13. }
  14. }
- 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. return rnd1.Next(100);
  7. }
  8. static public int randomColorFactor()
  9. {
  10. return rnd1.Next(255);
  11. }
  12. }
- 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. public void SetLineChartData()
  9. {
  10. lineChartData = new int[7];
  11. lineChartData[0] = RandomNumberGenerator.randomScalingFactor();
  12. lineChartData[1] = RandomNumberGenerator.randomScalingFactor();
  13. lineChartData[2] = RandomNumberGenerator.randomScalingFactor();
  14. lineChartData[3] = RandomNumberGenerator.randomScalingFactor();
  15. lineChartData[4] = RandomNumberGenerator.randomScalingFactor();
  16. lineChartData[5] = RandomNumberGenerator.randomScalingFactor();
  17. lineChartData[6] = RandomNumberGenerator.randomScalingFactor();
  18. colorString = "rgba(" + RandomNumberGenerator.randomColorFactor() + "," + RandomNumberGenerator.randomColorFactor() + "," + RandomNumberGenerator.randomColorFactor() + ",.3)";
  19. }
  20. }

- 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. public void SetPieChartData()
  7. {
  8. pieChartData = new int[3];
  9. pieChartData[0] = RandomNumberGenerator.randomScalingFactor();
  10. pieChartData[1] = RandomNumberGenerator.randomScalingFactor();
  11. pieChartData[2] = RandomNumberGenerator.randomScalingFactor();
  12. }
  13. }
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.
  1. public class ChartDataUpdate
  2. {
  3. // Singleton instance
  4. private readonly static Lazy<ChartDataUpdate> _instance = new Lazy<ChartDataUpdate>(() => new ChartDataUpdate());
  5. // Send Data every 5 seconds
  6. readonly int _updateInterval = 5000;
  7. //Timer Class
  8. private Timer _timer;
  9. private volatile bool _sendingChartData = false;
  10. private readonly object _chartUpateLock = new object();
  11. LineChart lineChart = new LineChart();
  12. PieChart pieChart = new PieChart();
  13. private ChartDataUpdate()
  14. {
  15. }
  16. public static ChartDataUpdate Instance
  17. {
  18. get
  19. {
  20. return _instance.Value;
  21. }
  22. }
  23. // Calling this method starts the Timer
  24. public void GetChartData()
  25. {
  26. _timer = new Timer(ChartTimerCallBack, null, _updateInterval, _updateInterval);
  27. }
  28. private void ChartTimerCallBack(object state)
  29. {
  30. if (_sendingChartData)
  31. {
  32. return;
  33. }
  34. lock (_chartUpateLock)
  35. {
  36. if (!_sendingChartData)
  37. {
  38. _sendingChartData = true;
  39. SendChartData();
  40. _sendingChartData = false;
  41. }
  42. }
  43. }
  44. private void SendChartData()
  45. {
  46. lineChart.SetLineChartData();
  47. pieChart.SetPieChartData();
  48. GetAllClients().All.UpdateChart(lineChart,pieChart);
  49. }
  50. private static dynamic GetAllClients()
  51. {
  52. return GlobalHost.ConnectionManager.GetHubContext<ChartHub>().Clients;
  53. }
  54. }
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. namespace RealTimeChart
  7. {
  8. public class ChartHub : Hub
  9. {
  10. // Create the instance of ChartDataUpdate
  11. private readonly ChartDataUpdate _ChartInstance;
  12. public ChartHub() : this(ChartDataUpdate.Instance) { }
  13. public ChartHub(ChartDataUpdate ChartInstance)
  14. {
  15. _ChartInstance = ChartInstance;
  16. }
  17. public void InitChartData()
  18. {
  19. //Show Chart initially when InitChartData called first time
  20. LineChart lineChart = new LineChart();
  21. PieChart pieChart = new PieChart();
  22. lineChart.SetLineChartData();
  23. pieChart.SetPieChartData();
  24. Clients.All.UpdateChart(lineChart,pieChart);
  25. //Call GetChartData to send Chart data every 5 seconds
  26. _ChartInstance.GetChartData();
  27. }
  28. }
  29. }
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. </td>
  6. <td style="width: 50%; text-align: center">
  7. <canvas id="canvasForPieChart" height="200" width="400">Chart is Loading...</canvas>
  8. </td>
  9. </tr>
  10. </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. else {
  11. document.write("Browser doesn't support HTML5 2D Context");
  12. return false;
  13. }
  14. }
  15. $(function () {
  16. //If not HTML5 Support the Exit
  17. if (checkHTML5() == false) return;
  18. //Create the Hub
  19. var chartHub = $.connection.chartHub;
  20. //Call InitChartData
  21. $.connection.hub.start().done(function () {
  22. chartHub.server.initChartData();
  23. });
  24. //Call to Update LineChart from Server
  25. chartHub.client.updateChart = function (line_data,pie_data) {
  26. UpdateLineChart(line_data); //Call the LineChart Update method
  27. UpdatePieChart(pie_data); //Call the PieChart Update method
  28. };
  29. });
  30. </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. //Pie Chart JSON Config (Pie Chart Has fixed 3 Values/Slices here)
  14. var pieChartdata = [
  15. {
  16. value: 0,
  17. color: "#F7464A",
  18. label: "East"
  19. },
  20. {
  21. value: 0,
  22. color: "#46BFBD",
  23. label: "West"
  24. },
  25. {
  26. value: 0,
  27. color: "#FDB45C",
  28. label: "North"
  29. },
  30. {
  31. value: 0,
  32. color: "#FE94DC",
  33. label: "South"
  34. }
  35. ]
  36. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  37. //PieChart Update method
  38. function UpdatePieChart(data) {
  39. //Set data returned from Server
  40. pieChartdata[0].value = data.value[0];
  41. pieChartdata[1].value = data.value[1];
  42. pieChartdata[2].value = data.value[2];
  43. //Update the Line Chart
  44. var canvasForPieChart = document.getElementById("canvasForPieChart");
  45. var context2DPie = canvasForPieChart.getContext("2d");
  46. new Chart(context2DPie).Pie(pieChartdata);
  47. }
  48. //LineChart Update method
  49. function UpdateLineChart(data) {
  50. //Set data returned from Server
  51. lineChartData.datasets[0].fillColor = data.colorString;
  52. lineChartData.datasets[0].data = data.lineChartData;
  53. //Update the Pie Chart
  54. var canvasForLineChart = document.getElementById("canvasForLineChart");
  55. var context2DLine = canvasForLineChart.getContext("2d");
  56. new Chart(context2DLine).Line(lineChartData);
  57. }
  58. </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

Link to my other SignalR Article "Simple Drawing in SignalR Using Visual Studio 2012" .

Have a nice Day. :-)