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.
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Threading;
- using Microsoft.AspNet.SignalR;
- using Microsoft.AspNet.SignalR.Hubs;
- using Newtonsoft.Json;
-
- namespace RealTimeChart
- {
-
-
- public class ChartDataUpdate
- {
- }
- }
- 4.2 Add the
RandamNumberGenerator class in
ChartDataUpdate.cs. This class generates a Random Number for the Chart Data.
- public class RandomNumberGenerator
- {
- static Random rnd1 = new Random();
- static public int randomScalingFactor()
- {
-
- return rnd1.Next(100);
- }
- static public int randomColorFactor()
- {
-
- return rnd1.Next(255);
- }
- }
- 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.
-
- public class LineChart
- {
- [JsonProperty("lineChartData")]
- private int[] lineChartData;
- [JsonProperty("colorString")]
- private string colorString;
-
- public void SetLineChartData()
- {
- lineChartData = new int[7];
- lineChartData[0] = RandomNumberGenerator.randomScalingFactor();
- lineChartData[1] = RandomNumberGenerator.randomScalingFactor();
- lineChartData[2] = RandomNumberGenerator.randomScalingFactor();
- lineChartData[3] = RandomNumberGenerator.randomScalingFactor();
- lineChartData[4] = RandomNumberGenerator.randomScalingFactor();
- lineChartData[5] = RandomNumberGenerator.randomScalingFactor();
- lineChartData[6] = RandomNumberGenerator.randomScalingFactor();
-
- colorString = "rgba(" + RandomNumberGenerator.randomColorFactor() + "," + RandomNumberGenerator.randomColorFactor() + "," + RandomNumberGenerator.randomColorFactor() + ",.3)";
- }
- }
- 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.
-
- public class PieChart
- {
- [JsonProperty("value")]
- private int[] pieChartData;
-
- public void SetPieChartData()
- {
- pieChartData = new int[3];
- pieChartData[0] = RandomNumberGenerator.randomScalingFactor();
- pieChartData[1] = RandomNumberGenerator.randomScalingFactor();
- pieChartData[2] = RandomNumberGenerator.randomScalingFactor();
-
- }
-
- }
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.
- public class ChartDataUpdate
- {
-
-
- private readonly static Lazy<ChartDataUpdate> _instance = new Lazy<ChartDataUpdate>(() => new ChartDataUpdate());
-
- readonly int _updateInterval = 5000;
-
- private Timer _timer;
- private volatile bool _sendingChartData = false;
- private readonly object _chartUpateLock = new object();
- LineChart lineChart = new LineChart();
- PieChart pieChart = new PieChart();
-
- private ChartDataUpdate()
- {
-
- }
-
- public static ChartDataUpdate Instance
- {
- get
- {
- return _instance.Value;
- }
- }
-
-
- public void GetChartData()
- {
- _timer = new Timer(ChartTimerCallBack, null, _updateInterval, _updateInterval);
-
- }
- private void ChartTimerCallBack(object state)
- {
- if (_sendingChartData)
- {
- return;
- }
- lock (_chartUpateLock)
- {
- if (!_sendingChartData)
- {
- _sendingChartData = true;
- SendChartData();
- _sendingChartData = false;
- }
- }
- }
-
- private void SendChartData()
- {
- lineChart.SetLineChartData();
- pieChart.SetPieChartData();
- GetAllClients().All.UpdateChart(lineChart,pieChart);
-
- }
-
- private static dynamic GetAllClients()
- {
- return GlobalHost.ConnectionManager.GetHubContext<ChartHub>().Clients;
- }
-
- }
Step 5
Create the Chart Hub Class.
Right-click the Project folder then seelct Add > Class.. then type the class name as ChartHub.cs.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using Microsoft.AspNet.SignalR;
-
- namespace RealTimeChart
- {
-
- public class ChartHub : Hub
- {
-
- private readonly ChartDataUpdate _ChartInstance;
- public ChartHub() : this(ChartDataUpdate.Instance) { }
-
- public ChartHub(ChartDataUpdate ChartInstance)
- {
- _ChartInstance = ChartInstance;
- }
-
- public void InitChartData()
- {
-
- LineChart lineChart = new LineChart();
- PieChart pieChart = new PieChart();
- lineChart.SetLineChartData();
- pieChart.SetPieChartData();
- Clients.All.UpdateChart(lineChart,pieChart);
-
-
-
- _ChartInstance.GetChartData();
-
- }
-
- }
- }
Step 6
Create the OWIN Startup Class.
Right-click the Project folder then seelct Add > Class.. then type the class name as Startup.cs.
- using System;
- using Microsoft.Owin;
- using Owin;
- [assembly: OwinStartup(typeof(RealTimeChart.Startup))]
- namespace RealTimeChart
- {
- public class Startup
- {
- public void Configuration(IAppBuilder app)
- {
-
- app.MapSignalR();
- }
- }
- }
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:
- <script src="Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
- <script src="Scripts/Chart.min.js" type="text/javascript"></script>
Then add a reference to the required SignalR JavaScript files as in the following:
- <script src="Scripts/jquery-ui-1.8.20.min.js"></script>
- <script src="Scripts/jquery.signalR-2.2.0.min.js"></script>
- <script src="/signalr/hubs"></script>
Add a Canvas area where the Line and Pie charts will be displayed as in the following:
- <table style="width: 100%">
- <tr>
- <td style="width: 50%; text-align: center">
- <canvas id="canvasForLineChart" height="200" width="400">Chart is Loading...</canvas>
-
- </td>
- <td style="width: 50%; text-align: center">
- <canvas id="canvasForPieChart" height="200" width="400">Chart is Loading...</canvas>
- </td>
- </tr>
- </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.
- <script>
- function checkHTML5() {
- var canvasForLineChart = document.getElementById("canvasForLineChart");
- if (canvasForLineChart == null || canvasForLineChart == "") {
- document.write("Browser doesn't support HTML5 2D Context");
- return false;
- }
- if (canvasForLineChart.getContext) {
-
- }
- else {
- document.write("Browser doesn't support HTML5 2D Context");
- return false;
- }
- }
-
- $(function () {
-
- if (checkHTML5() == false) return;
-
-
- var chartHub = $.connection.chartHub;
-
-
-
- $.connection.hub.start().done(function () {
- chartHub.server.initChartData();
-
- });
-
-
- chartHub.client.updateChart = function (line_data,pie_data) {
- UpdateLineChart(line_data);
- UpdatePieChart(pie_data);
- };
-
-
- });
- </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.
- <script type="text/javascript">
-
-
- var lineChartData = {
- labels: ["January", "February", "March", "April", "May", "June", "July"],
- datasets: [
- {
- fillColor: "",
- data: [0]
- }
- ]
-
- }
-
-
- var pieChartdata = [
- {
- value: 0,
- color: "#F7464A",
- label: "East"
- },
- {
- value: 0,
- color: "#46BFBD",
- label: "West"
- },
- {
- value: 0,
- color: "#FDB45C",
- label: "North"
- },
- {
- value: 0,
- color: "#FE94DC",
- label: "South"
- }
- ]
-
-
-
-
- function UpdatePieChart(data) {
-
- pieChartdata[0].value = data.value[0];
- pieChartdata[1].value = data.value[1];
- pieChartdata[2].value = data.value[2];
-
- var canvasForPieChart = document.getElementById("canvasForPieChart");
- var context2DPie = canvasForPieChart.getContext("2d");
- new Chart(context2DPie).Pie(pieChartdata);
-
- }
-
-
- function UpdateLineChart(data) {
-
- lineChartData.datasets[0].fillColor = data.colorString;
- lineChartData.datasets[0].data = data.lineChartData;
-
- var canvasForLineChart = document.getElementById("canvasForLineChart");
- var context2DLine = canvasForLineChart.getContext("2d");
- new Chart(context2DLine).Line(lineChartData);
- }
-
- </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.
Have a nice Day. :-)