In this post, I will show how to create charts using Asp.net core. We will select a JavaScript library and create a ViewComponent to make life a little easier when using charts in ASP.NET Core.
The New World: Everything JavaScript
When ASP.NET MVC came around, there was already a charting library for the server from Microsoft. The Chart Class in the WebPages 3.2 WebHelper assembly helped to generate charts on the server and then return the image to the client.
That was 5 years ago.
The new normal of creating charts is through the use of this new thing called JavaScript (anyone heard of it? </sarcasm>).
As you know, there are a number of JavaScript charting libraries available through even the biggest companies like Google. The one downside to every JavaScript is the data has to be JSON. It would be easier to retrieve the data and create the chart on the server, then return the generated chart to the client.
However, everyone wants their charts to be dynamic. It’s kind of hard to add a new series of data to an axis, change a label, or click on an item to examine data further when you are sent a static image from the server. Interaction and JavaScript go hand-in-hand when it comes to client-side charting.
JavaScript Charting Libraries
Let’s select a JavaScript library. Even though there are a ton out there, I’ve found a couple of mature libraries.
The charting libraries I’m aware of are the following:
I wanted to create a simple demonstration so we’ll use ChartsJs for this example.
But how do we send data from C# over to JavaScript to display in our chart.
The Basics of ASP.NET Core ViewComponents
Let’s review the basics of ViewComponents.
- ViewComponents have a specific signature for their tagname. Ours will be
chartjs
and have a prefix of vc. (i.e.<vc:chartjs>
) _ViewImports.cshtml
must have an @addTagHelper with the assembly name containing your ViewComponents.- ViewComponents can disguise themselves as TagHelper as tags (which looks more natural)
- ViewComponents are identified by deriving from a ViewComponent, decorating a class with a
[ViewComponent]
attribute, or creating a class that ends with ViewComponent - ViewComponents can be placed anywhere in the project.
- The Views are placed in the
Views/Shared/Components/{viewcomponentname}/default.cshtml
directory. You can also customize the search path for your View locations as well.
Quite a checklist to make sure we are creating a ViewComponent properly, but the dividends are worth it in the end.
Building the Chart Structure
For this example, we’ll create the simple chart from the ChartJs page.
However, we need a Json structure for our chart data. The quickest way to create a C# structure from JSON is the following:
- Copy the JSON structure in the example (JUST the JSON structure)
- Create a new class in Visual Studio 2019
- Under Edit -> Paste Special -> Paste Json as classes.
- Rename the “RootObject” to “ChartJs”
Voila! You now have a complete C# class that mimics the JSON example required for the chart.
We create the C# class for two reasons:
- It’s easier to manage a C# class hierarchy instead of concatenating strings.
- It can be data-driven by saving titles, labels, and chart types for customization purposes.
Let’s move on to the ViewComponent.
Creating the Chart ViewComponent
Now that we have the chart model, we can proceed with our ViewComponent.
Of course, this was a VERY quick implementation of our ViewComponent.
ViewComponents/ChartJsViewComponent.cs
using ChartExample.Models;
using ChartExample.Models.Chart;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace ChartExample.ViewComponents
{
[ViewComponent(Name = "chartjs")]
public class ChartJsViewComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
// Ref: https://www.chartjs.org/docs/latest/
var chartData = @"
{
type: 'bar',
responsive: true,
data:
{
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options:
{
scales:
{
yAxes: [{
ticks:
{
beginAtZero: true
}
}]
}
}
}";
var chart = JsonConvert.DeserializeObject<ChartJs>(chartData);
var chartModel = new ChartJsViewModel
{
Chart = chart,
ChartJson = JsonConvert.SerializeObject(chart, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore })
};
return View(chartModel);
}
}
}
Our simple ChartJsViewModel only has two members: Chart and ChartJson. I also wanted to take the sample JSON and confirm it deserialized properly into our ChartJs object.
Models/ChartJsViewModel.cs
public class ChartJsViewModel
{
public ChartJs Chart { get; set; }
public string ChartJson { get; set; }
}
With our ViewComponent done, we need the complimentary View to draw our chart.
Views/Shared/Components/ChartJs/default.cshtml
@model ChartJsViewModel
<div class="chart-container" width="600" height="400">
<canvas id="myChart"></canvas>
</div>
<script>
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, @Html.Raw(Model.ChartJson) );
</script>
Our ChartJs component is done. Time to test it out.
Missing Functionality
When I ran the example for the first time, I got a blank section where the chart was supposed to be.
After looking over the code, I forgot the following:
- Add the @addTagHelper to the _ViewImports.cshtml
@addTagHelper *, ChartExample - Add the tag to the Home/Index page (view)
<vc:chartjs></vc:chartjs>
After adding these two items, I ran the example again and noticed the ViewComponent’s View was loading properly, but the JavaScript wasn’t executed to display my chart.
After experimenting, I found out we need to wrap our JavaScript with a DOMContentLoaded event listener to make this example work.
@model ChartJsViewModel
<div class="chart-container" width="600" height="400">
<canvas id="myChart"></canvas>
</div>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, @Html.Raw(Model.ChartJson) );
});
</script>
Our Results
We now have a chart component allowing us to send the data to the client in a Json format to display our interactive chart.
Conclusion
While this is a very simple demonstration of how to send data from ASP.NET Core to a JavaScript Chart library, you can dig into this further by:
- Building Other Charts – This is only one bar chart. Build more C# objects based on the examples and documentation provided on the site.
- Data-Driven Charts – Use Entity Framework to return data for your charts.
- Various Charting Libraries – ChartJs is just one example. With this model, you can easily create an ASP.NET Core library from any of the Charting libraries from above.
- KPI Charting – Create dashboard widgets with interactive, dynamic charts to make (hmmm…) 😉
I hope this provides a better understanding of how to utilize JavaScript charts with ASP.NET Core.