Showing posts with label google chart. Show all posts
Showing posts with label google chart. Show all posts

Sunday, January 2, 2022

Google charts with DataTable .NET Wrapper and API data in ASP.NET 6.0 Razor Pages App

You have data from an API (or any other data source like a database) and wish to display the results in a chart. The library we will use for generating charts is the freely available Google Charts JavaScript-based API. The Google DataTable .NET Wrapper is used to create a lightweight representation of the google.visualization.DataTable object directly in Microsoft.NET. The wrapper allows for the creation of the appropriate JSON which is easily ingested by the Google Chart Tools JavaScript library.

I will show you how to generate six types of charts to display dynamically generated data. The source of data will be an API at https://northwind.vercel.app/api/orders that displays orders. I will work with the ASP.NET Razor Pages template (AKA Web App).

Source code:  https://github.com/medhatelmasry/OrdersChartRazorGoogleWrapper

Companion Video: https://youtu.be/Ie43mv57-5o

The environment I am using is: https://github.com/medhatelmasry/OrdersChartRazorGoogleWrapper

  • .NET version 6.0.100
  • Visual Studio Code

The orders API

We will work with the orders API at https://northwind.vercel.app/api/orders. The data in the API is generated from the well known Northwind sample SQL Server database. If you point your browser to the above address, you will see the following:



Since some properties are not useful in this tutorial, we will ignore orderDate, requiredDate, shippedDate, postalCode and details.

Also, note that shipAddress is represented by a sub JSON address object.

Project setup

Run the following command to create an ASP.NET Core Razor Pages application using .NET 6.0 in a folder named OrdersChartRazorGoogleWrapper:

dotnet new razor -f net6.0 -o OrdersChartRazorGoogleWrapper

Change directory into the new folder and open the project inside VS Code with the following commands:

cd OrdersChartRazorGoogleWrapper 

code .


Install the Google DataTable .NET Wrapper Nuget package:

dotnet add package Google.DataTable.Net.Wrapper

Address & Order model classes

Create a folder named Models. Add to the Models folder two class files, namely: Address.cs and Order.cs

The Address class looks like this:

public class Address {
    [JsonPropertyName("street")]
    public string? Street { get; set; }


    [JsonPropertyName("city")]
    public string? City { get; set; }


    [JsonPropertyName("region")]
    public string? Region { get; set; }


    [JsonPropertyName("country")]
    public string? Country { get; set; }

}

The Order class looks like this:

public class Order {
    [JsonPropertyName("id")]
    public int Id { get; set; }


    [JsonPropertyName("customerId")]
    public string? CustomerId { get; set; }


    [JsonPropertyName("employeeId")]
    public int? EmployeeId { get; set; }


    [JsonPropertyName("shipVia")]
    public int? ShipVia { get; set; }

    
    [JsonPropertyName("freight")]
    public decimal? Freight { get; set; }


    [JsonPropertyName("shipName")]
    public string? ShipName { get; set; }


    [JsonPropertyName("shipAddress")]
    public Address ShipAddress { get; set; } = null!;
}

Reading data

In the Pages folder, add two files ChartData.cshtml and ChartData.cshtml.cs.

Content of ChartData.cshtml is:

@page
@model ChartDataModel

Content of ChartData.cshtml.cs is:

using System.Text.Json;
using Google.DataTable.Net.Wrapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using OrdersChartRazorGoogleWrapper.Models;

namespace OrdersChartRazorGoogleWrapper.Pages;

public class ChartDataModel : PageModel {
    private readonly ILogger<ChartDataModel> _logger;

    public ChartDataModel(ILogger<ChartDataModel> logger) {
        _logger = logger;
    }

    public async Task<IActionResult> OnGet() {
        Order[] orders = await GetOrdersAsync();

        var data = orders
          .GroupBy(_ => _.ShipAddress.City)
          .Select(g => new
          {
              Name = g.Key,
              Count = g.Count()
          })
          .OrderByDescending(cp => cp.Count)
          .ToList();


        //let's instantiate the DataTable.
        var dt = new Google.DataTable.Net.Wrapper.DataTable();
        dt.AddColumn(new Column(ColumnType.String, "Name", "Name"));
        dt.AddColumn(new Column(ColumnType.Number, "Count", "Count"));

        foreach (var item in data) {
            Row r = dt.NewRow();
            r.AddCellRange(new Cell[] {
              new Cell(item.Name),
              new Cell(item.Count)
            });
            dt.AddRow(r);
        }

        //Let's create a Json string as expected by the Google Charts API.
        return Content(dt.GetJson());
    }

    private async Task<Order[]> GetOrdersAsync() {
        HttpClient client = new HttpClient();
        var stream = client.GetStreamAsync("https://northwind.vercel.app/api/orders");
        var orders = await JsonSerializer.DeserializeAsync<Order[]>(await stream);

        return orders!;
    }
}


The above code in ChartData.cshtml.cs returns a JSON representation of  Google.DataTable.Net.Wrapper.DataTable. It contains data from the Orders API representing the number of orders by city.

At this stage, let's run our web application and verify that we are indeed able to read data from the Orders API and subsequently generate JSON data. Run your application with:

dotnet watch run

Point your browser to https://localhost:7205/chartdata

NOTE: you will need to adjust the port number to suit your environment.

This is what was revealed in my browser:


We have a sense of assurance that our data is ready to be displayed in a chart.

Charting the data

Let's first generate a simple column-chart. Replace your Pages/Index.cshtml with the following code:

@page
@model IndexModel
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

<div id="column_chart_div"></div>
<script type="text/javascript">

    google.charts.load('current', {
        packages: ['corechart', 'bar']
    });
    google.setOnLoadCallback(drawChart);

    function drawChart() {
        var jsonData = $.ajax({
            url: '/ChartData',
            dataType: "json",
            async: false
        }).responseText;
         // Create our data table out of JSON data loaded from server.
        var data = new google.visualization.DataTable(jsonData);
        var options = { title: 'Orders by city' };
        var chart = new google.visualization.ColumnChart(document.getElementById('column_chart_div'));
        chart.draw(data, options);
    }

</script>

Point your browser to the home page, you should see a column-chart as follows:


If you want to see more types of charts, replace Pages/Index.cshtml with the following code:

@page
@model IndexModel

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

<div id="column_chart_div"></div>
<div id="line_chart_div"></div>
<div id="pie_chart_div"></div>
<div id="area_chart_div"></div>
<div id="bar_chart_div"></div>
<div id="pie_chart_3d_div"></div>


<script type="text/javascript">
    google.charts.load('current', {
        packages: ['corechart', 'bar']
    });

    google.setOnLoadCallback(drawChart);

    function drawChart() {
        var jsonData = $.ajax({
            url: '/ChartData',
            dataType: "json",
            async: false
        }).responseText;

        PopulationChart(jsonData, "column-chart");
        PopulationChart(jsonData, "line-chart");
        PopulationChart(jsonData, "pie-chart");
        PopulationChart(jsonData, "area-chart");
        PopulationChart(jsonData, "bar-chart");
        PopulationChart(jsonData, "pie-chart-3d");
    }

    function PopulationChart(jsonData, chart_type) {
        // Create our data table out of JSON data loaded from server.
        var data = new google.visualization.DataTable(jsonData);
        var chart;
        var options = { title: 'Orders by city' };

        switch (chart_type) {

            case "line-chart":
                chart = new google.visualization.LineChart(document.getElementById('line_chart_div'));
                break;
            case "pie-chart":
                chart = new google.visualization.PieChart(document.getElementById('pie_chart_div'));
                break;
            case "area-chart":
                chart = new google.visualization.AreaChart(document.getElementById('area_chart_div'));
                break;
            case "bar-chart":
                chart = new google.visualization.BarChart(document.getElementById('bar_chart_div'));
                break;
            case "pie-chart-3d":
                options.is3D = true;
                chart = new google.visualization.PieChart(document.getElementById('pie_chart_3d_div'));
                break;
            default:
                chart = new google.visualization.ColumnChart(document.getElementById('column_chart_div'));
                break;
        }

        chart.draw(data, options);
        return false;
    }

</script>    

You should see six charts on the home page, namely: column, line, pie, area, bar and pie 3D charts.




Conclusion

It is very easy and inexpensive (free) to use Google Charts to generate charts in an ASP.NET Razor application. The .NET Google DataTable wrapper (Google.DataTable.Net.Wrapper) makes it even easier.

Monday, December 20, 2021

Generate charts with Google DataTable .NET Wrapper from ASP.NET 6.0 Razor Pages App

The scenario that this article addresses is a situation whereby there is server-side generated data that needs to be displayed on a web page as a chart. The API used for generating the chart is the freely available Google Charts JavaScript-based API. The Google DataTable .NET Wrapper is used to create a lightweight representation of the google.visualization.DataTable object directly in Microsoft.NET. The wrapper allows for the creation of the appropriate JSON which is easily ingested by the Google Chart Tools JavaScript library.

I will show you how to generate six types of charts to display dynamically generated data. The source of data will be the well known Northwind database running in a Docker container. I will work with the ASP.NET Razor Pages template (AKA Web App).

Source code:  https://github.com/medhatelmasry/ChartRazorGoogleWrapper

The environment I am using is: 

  • Windows 11
  • Docker Desktop for Windows
  • .NET version 6.0.100
  • Visual Studio Code

Start Northwind database in a Docker container

To pull & run the Northwind database in a Docker container, run the following command in a terminal window:

docker run -d --name nw -p 1444:1433 kcornwall/sqlnorthwind

The above command does the following:

Docker image:kcornwall/sqlnorthwind
Container Name (--name):nw
Ports (-p):Port 1433 in container is exposed as port 1444 on the host computer
Password:The sa password is Passw0rd2018. This was determined from the Docker Hub page for the image.
-d:Starts the container in detached mode

This is what I experienced after I ran the above command:


Let us make sure that the container is running. Execute this command to ensure that the container is indeed running.

docker ps

The following confirmed to me that the container is running:

Project setup

Run the following command to create an ASP.NET Core MVC application using .NET 6.0 in a folder named ChartRazorGoogleWrapper:

dotnet new razor -f net6.0 -o ChartRazorGoogleWrapper

Change directory into the new folder and open the project inside VS Code with the following commands:

cd ChartRazorGoogleWrapper 

code .

We will need to install an Entity Framework command-line utility. If you have not done so already, install dotnet-ef with this command:

dotnet tool install –g dotnet-ef 

It does not hurt to upgrade this tool to the latest version with:

dotnet tool update -g dotnet-ef

Also, from within the root folder of your project, add some SQL-Server and Entity Framework related packages with the following terminal-window commands:

dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools


Also, install the Google DataTable .NET Wrapper Nuget package:

dotnet add package Google.DataTable.Net.Wrapper

In appsettings.json, add this to ConnectionStrings block just before “Logging”:

"ConnectionStrings": {
    "NW": "Data Source=localhost,1444;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=Passw0rd2018"
},

Next, let us reverse engineer only the Orders entities in the Northwind database. Execute this command from the root of your project:

dotnet-ef dbcontext scaffold "Data Source=localhost,1444;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=Passw0rd2018" Microsoft.EntityFrameworkCore.SqlServer -c NorthwindContext -o NW --table Orders

This creates a NW folder in your project with entity Orders and database context class NorthwindContext.


Delete the OnConfiguring() method in NorthwindContext.cs so that there is no hard-coded connection string in our C# code.

Add the following code to Program.cs right after where the variable builder is declared:

var connectionString = builder.Configuration.GetConnectionString("NW");
builder.Services.AddDbContext<NorthwindContext>(options => {
  options.UseSqlServer(connectionString);
});

Reading data

In the Pages folder, add two files ChartData.cshtml and ChartData.cshtml.cs.

Content of ChartData.cshtml is:

@page
@model ChartDataModel

Content of ChartData.cshtml.cs is:

using ChartRazorGoogleWrapper.NW;
using Google.DataTable.Net.Wrapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;

namespace ChartRazorGoogleWrapper.Pages;

public class ChartDataModel : PageModel {
   private readonly ILogger<ChartDataModel> _logger;
   private readonly NorthwindContext _northwindContext;

   public ChartDataModel(ILogger<ChartDataModel> logger, NorthwindContext northwindContext) {
     _logger = logger;
     _northwindContext = northwindContext;
   }

   public async Task<IActionResult> OnGet() {
     var data = await _northwindContext.Orders
     .GroupBy(_ => _.ShipCity)
     .Select(g => new {
         Name = g.Key,
         Count = g.Count()
     })
     .OrderByDescending(cp => cp.Count)
     .ToListAsync();

     //let's instantiate the DataTable.
     var dt = new Google.DataTable.Net.Wrapper.DataTable();
     dt.AddColumn(new Column(ColumnType.String, "Name", "Name"));
     dt.AddColumn(new Column(ColumnType.Number, "Count", "Count"));

     foreach (var item in data) {
         Row r = dt.NewRow();
         r.AddCellRange(new Cell[] {
             new Cell(item.Name),
             new Cell(item.Count)
         });
         dt.AddRow(r);
     }

     //Let's create a Json string as expected by the Google Charts API.
     return Content(dt.GetJson());
   }
}

The above code in ChartData.cshtml.cs returns a JSON representation of  Google.DataTable.Net.Wrapper.DataTable. It contains data from the Northwind database representing the number of orders by city.

At this stage, let's run our web application and verify that we are indeed able to read data from the Northwind database and subsequently generate JSON data. Run your application with:

dotnet watch run

Point your browser to https://localhost:7108/chartdata

NOTE: you will need to adjust the port number to suit your environment.

This is what was revealed in my browser:


We have a sense of assurance that our data is ready to be displayed in a chart.

Charting the data

Replace your Pages/Index.cshtml with the following code:

@page
@model IndexModel

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

<div id="column_chart_div"></div>
<div id="line_chart_div"></div>
<div id="pie_chart_div"></div>
<div id="area_chart_div"></div>
<div id="bar_chart_div"></div>
<div id="pie_chart_3d_div"></div>


<script type="text/javascript">
    google.charts.load('current', {
        packages: ['corechart', 'bar']
    });

    google.setOnLoadCallback(drawChart);

    function drawChart() {
        var jsonData = $.ajax({
            url: '/ChartData',
            dataType: "json",
            async: false
        }).responseText;

        PopulationChart(jsonData, "column-chart");
        PopulationChart(jsonData, "line-chart");
        PopulationChart(jsonData, "pie-chart");
        PopulationChart(jsonData, "area-chart");
        PopulationChart(jsonData, "bar-chart");
        PopulationChart(jsonData, "pie-chart-3d");
    }

    function PopulationChart(jsonData, chart_type) {
        // Create our data table out of JSON data loaded from server.
        var data = new google.visualization.DataTable(jsonData);
        var chart;
        var options = { title: 'Orders by city' };

        switch (chart_type) {

            case "line-chart":
                chart = new google.visualization.LineChart(document.getElementById('line_chart_div'));
                break;
            case "pie-chart":
                chart = new google.visualization.PieChart(document.getElementById('pie_chart_div'));
                break;
            case "area-chart":
                chart = new google.visualization.AreaChart(document.getElementById('area_chart_div'));
                break;
            case "bar-chart":
                chart = new google.visualization.BarChart(document.getElementById('bar_chart_div'));
                break;
            case "pie-chart-3d":
                options.is3D = true;
                chart = new google.visualization.PieChart(document.getElementById('pie_chart_3d_div'));
                break;
            default:
                chart = new google.visualization.ColumnChart(document.getElementById('column_chart_div'));
                break;
        }

        chart.draw(data, options);
        return false;
    }

</script>    

If you point your browser to the home page, you should see six charts, namely: column, line, pie, area, bar and pie 3D charts.




Conclusion

This shows you how the Google Chart Tools JavaScript library makes it much easier to generate charts from an ASP.NET Razor application.


Sunday, December 19, 2021

Using Google Charts API with an ASP.NET Core 6.0 Razor Pages App

Google Charts is a free JavaScript API that you can use to generate good looking charts on a web page. Although it has nothing to do with C# and .NET, we can still use it in an ASP.NET application. I will show you how to generate five types of charts to display dynamically generated data. The source of data will be the well known Northwind database running in a Docker container.

In another article, I show how to use Google charts with an ASP.NET Core MVC application.  In this article, I work with the ASP.NET Razor Pages template (AKA Web App), instead.

Source code: https://github.com/medhatelmasry/gChartRazor

The environment I am using is:

  • Windows 11
  • Docker Desktop for Windows
  • .NET version 6.0.100
  • Visual Studio Code

Start Northwind database in a Docker container

To pull & run the Northwind database in a Docker container, run the following command in a terminal window:

docker run -d --name nw -p 1444:1433 kcornwall/sqlnorthwind

The above command does the following:

Docker image:kcornwall/sqlnorthwind
Container Name (--name):nw
Ports (-p):Port 1433 in container is exposed as port 1444 on the host computer
Password:The sa password is Passw0rd2018. This was determined from the Docker Hub page for the image.
-d:Starts the container in detached mode

This is what I experienced after I ran the above command:


Let us make sure that the container is running. Execute this command to ensure that the container is indeed running.

docker ps

The following confirmed to me that the container is running:

Project setup

Run the following command to create an ASP.NET Core razor pages application using .NET 6.0 in a folder named gChartRazor:

dotnet new razor -f net6.0 -o gChartRazor

Change directory into the new folder and open the project inside VS Code with the following commands:

cd gChartRazor 

code .

We will need to install an Entity Framework command-line utility. If you have not done so already, install dotnet-ef with this command:

dotnet tool install –g dotnet-ef 

It does not hurt to upgrade this tool to the latest version with:

dotnet tool update -g dotnet-ef

Also, from within the root folder of your project, add some SQL-Server and Entity Framework related packages with the following terminal-window commands:

dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

In appsettings.json, add this to ConnectionStrings block just before “Logging”:

"ConnectionStrings": {
    "NW": "Data Source=localhost,1444;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=Passw0rd2018"
},

Next, let us reverse engineer the Products Categories entities in the Northwind database. Execute this command from the root of your project:

dotnet-ef dbcontext scaffold "Data Source=localhost,1444;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=Passw0rd2018" Microsoft.EntityFrameworkCore.SqlServer -c NorthwindContext -o NW --table Products --table Categories

This creates a NW folder in your project with entities Category Product. It also adds the database context class NorthwindContext.



Delete the OnConfiguring() method in NorthwindContext.cs so that there is no hard-coded connection string in our C# code.

Add the following code to Program.cs right after where the variable builder is declared:

var connectionString = builder.Configuration.GetConnectionString("NW");
builder.Services.AddDbContext<NorthwindContext>(options => {
  options.UseSqlServer(connectionString);
});

Reading data

In the Pages folder, add two files ChartData.cshtml and ChartData.cshtml.cs.

Content of ChartData.cshtml is:

@page
@model ChartDataModel

Content of ChartData.cshtml.cs is:

using gChartRazor.NW;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;

namespace gChartRazor.Pages;

public class ChartDataModel : PageModel {
   private readonly ILogger<ChartDataModel> _logger;
   private readonly NorthwindContext _northwindContext;

   public ChartDataModel(ILogger<ChartDataModel> logger, NorthwindContext northwindContext) {
     _logger = logger;
     _northwindContext = northwindContext;
   }

   public async Task<JsonResult> OnGet() {
     var query = await _northwindContext.Products
     .Include(c => c.Category)
     .GroupBy(p => p.Category!.CategoryName)
     .Select(g => new
     {
         Name = g.Key,
         Count = g.Count()
     })
     .OrderByDescending(cp => cp.Count)
     .ToListAsync();

     return new JsonResult(query);
   }
}

The above code in ChartData.cshtml.cs returns a JSON array with data from the Northwind database representing the number of products in each category.

At this stage, let's run our web application and verify that we are indeed able to read data from the Northwind database and subsequently generate JSON data. Run your application with:

dotnet watch run

Point your browser to https://localhost:7108/chartdata

NOTE: you will need to adjust the port number to suit your environment.

This is what was revealed in my browser:


We have a sense of assurance that our data is ready to be displayed in a chart.

Charting the data

Replace your Pages/Index.cshtml with the following code:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<title>@ViewData["Title"] - Google Charts</title>  
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>  
  
<div id="column_chart_div"></div>  
<div id="line_chart_div"></div>  
<div id="pie_chart_div"></div>  
<div id="area_chart_div"></div>  
<div id="bar_chart_div"></div>  
<script type="text/javascript">  
  
   google.charts.load('current', {  
     packages: ['corechart', 'bar']  
   });  
   google.charts.setOnLoadCallback(LoadData);  
   function LoadData() {  
      $.ajax({  
         url: '/ChartData',  
         dataType: "json",  
         type: "GET",  
         error: function(xhr, status, error) {  
            toastr.error(xhr.responseText);  
         },  
         success: function(data) {  
            PopulationChart(data, "column-chart");  
            PopulationChart(data, "line-chart");  
            PopulationChart(data, "pie-chart");  
            PopulationChart(data, "area-chart"); 
            PopulationChart(data, "bar-chart"); 
            return false;  
         }  
      });  
      return false;  
   }  
   function PopulationChart(data, chart_type) {  
      var dataArray = [  
         ['Category', 'Product']  
      ];  
      $.each(data, function(i, item) {  
         dataArray.push([item.name, item.count]);  
      });  
      var data = google.visualization.arrayToDataTable(dataArray);  
      var options = {  
         title: 'Product count by category',  
         chartArea: {  
             width: '80%'  
         },  
         colors: ['#b0120a', '#7b1fa2', '#ffab91', '#d95f02'],  
         hAxis: {  
             title: 'Categories',  
             minValue: 0  
         },  
         vAxis: {  
             title: 'Product Count'  
         }  
      };  
      var chart;
      switch(chart_type) {
         case "line-chart":
            chart = new google.visualization.LineChart(document.getElementById('line_chart_div'));  
            break;
         case "pie-chart":
            chart = new google.visualization.PieChart(document.getElementById('pie_chart_div'));  
            break;
         case "area-chart":
            chart = new google.visualization.AreaChart(document.getElementById('area_chart_div'));  
            break;
         case "bar-chart":
            chart = new google.visualization.BarChart(document.getElementById('bar_chart_div'));  
            break;
         default:
            chart = new google.visualization.ColumnChart(document.getElementById('column_chart_div'));  
            break;
      }
      chart.draw(data, options);  
      return false;  
   }  
</script>    

If you point your browser to the home page, you should see five charts, namely: column, line, pie, area and bar charts.


Conclusion

I trust the above article helps you consider using Google Charts with ASP.NET Razor Pages to visually display data.




Saturday, December 18, 2021

Using Google Charts API with an ASP.NET Core 6.0 MVC app

Google Charts is a free JavaScript API that you can use to generate good looking charts on a web page. Although it has nothing to do with C# and .NET, we can still use it in an ASP.NET application. In this article, I will show you how to generate five types of charts to display dynamically generated data. The source of data will be the well known Northwind database running in a Docker container.

In another article, I show how to use Google charts with an ASP.NET Core Razor Pages application.  In this article, I work with the ASP.NET MVC template, instead.

Source code: https://github.com/medhatelmasry/gChartMVC

The environment I am using is:

  • Windows 11
  • Docker Desktop for Windows
  • .NET version 6.0.100
  • Visual Studio Code

Start Northwind database in a Docker container

To pull & run the Northwind database in a Docker container, run the following command in a terminal window:

docker run -d --name nw -p 1444:1433 kcornwall/sqlnorthwind

The above command does the following:

Docker image: kcornwall/sqlnorthwind
Container Name (--name): nw
Ports (-p): Port 1433 in container is exposed as port 1444 on the host computer
Password: The sa password is Passw0rd2018. This was determined from the Docker Hub page for the image.
-d: Starts the container in detached mode

This is what I experienced after I ran the above command:


Let us make sure that the container is running. Execute this command to ensure that the container is indeed running.

docker ps

The following confirmed to me that the container is running:

Project setup

Run the following command to create an ASP.NET Core MVC application using .NET 6.0 in a folder named gChartMVC:

dotnet new mvc -f net6.0 -o gChartMVC

Change directory into the new folder and open the project inside VS Code with the following commands:

cd gChartMVC 

code .

We will need to install an Entity Framework command-line utility. If you have not done so already, install dotnet-ef with this command:

dotnet tool install –g dotnet-ef 

It does not hurt to upgrade this tool to the latest version with:

dotnet tool update -g dotnet-ef

Also, from within the root folder of your project, add some SQL-Server and Entity Framework related packages with the following terminal-window commands:

dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

In appsettings.json, add this to ConnectionStrings block just before “Logging”:

"ConnectionStrings": {
    "NW": "Data Source=localhost,1444;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=Passw0rd2018"
},

Next, let us reverse engineer the Products & Categories entities in the Northwind database. Execute this command from the root of your project:

dotnet-ef dbcontext scaffold "Data Source=localhost,1444;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=Passw0rd2018" Microsoft.EntityFrameworkCore.SqlServer -c NorthwindContext -o NW --table Products --table Categories

This creates a NW folder in your project with entities Category & Product. It also adds the database context class NorthwindContext.



Delete the OnConfiguring() method in NorthwindContext.cs so that there is no hard-coded connection string in our C# code.

Add the following code to Program.cs right after where the variable builder is declared:

var connectionString = builder.Configuration.GetConnectionString("NW");
builder.Services.AddDbContext<NorthwindContext>(options => {
  options.UseSqlServer(connectionString);
});

Reading data

Let's take advantage of dependency injection to access the database through an instance of the NorthwindContext. Add the following instance variable declaration to the top of the HomeController class:

private readonly NorthwindContext _northwindContext;

Update the HomeController constructor so it looks like this:

public HomeController(ILogger<HomeController> logger, NorthwindContext northwindContext) {
  _logger = logger;
  _northwindContext = northwindContext;
}

We will next add a method to the HomeController that can be called from our JavaScript front-end that reads products by category. 

public async Task<JsonResult> ChartData() {
   var query = await _northwindContext.Products
     .Include(c => c.Category)
     .GroupBy(p => p.Category!.CategoryName)
     .Select(g => new
     {
         Name = g.Key,
         Count = g.Count()
     })
     .OrderByDescending(cp => cp.Count)
        .ToListAsync();

   return Json(query);
}

At this stage, let's run our web application and verify that we are indeed able to read data from the Northwind database and subsequently generate JSON data. Run your application with:

dotnet watch run

Point your browser to https://localhost:7108/home/chartdata

NOTE: you will need to adjust the port number to suit your environment.

This is what was revealed in my browser:


We have a sense of assurance that our data is ready to be displayed in a chart.

Charting the data

Replace your Views/Home/Index.cshtml with the following code:

<title>@ViewData["Title"] - Google Charts</title>  
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>  
  
<div id="column_chart_div"></div>  
<div id="line_chart_div"></div>  
<div id="pie_chart_div"></div>  
<div id="area_chart_div"></div>  
<div id="bar_chart_div"></div>  
<script type="text/javascript">  
  
   google.charts.load('current', {  
     packages: ['corechart', 'bar']  
   });  
   google.charts.setOnLoadCallback(LoadData);  
   function LoadData() {  
      $.ajax({  
         url: '/Home/ChartData',  
         dataType: "json",  
         type: "GET",  
         error: function(xhr, status, error) {  
            toastr.error(xhr.responseText);  
         },  
         success: function(data) {  
            PopulationChart(data, "column-chart");  
            PopulationChart(data, "line-chart");  
            PopulationChart(data, "pie-chart");  
            PopulationChart(data, "area-chart"); 
            PopulationChart(data, "bar-chart"); 
            return false;  
         }  
      });  
      return false;  
   }  
   function PopulationChart(data, chart_type) {  
      var dataArray = [  
         ['Category', 'Product']  
      ];  
      $.each(data, function(i, item) {  
         dataArray.push([item.name, item.count]);  
      });  
      var data = google.visualization.arrayToDataTable(dataArray);  
      var options = {  
         title: 'Product count by category',  
         chartArea: {  
             width: '80%'  
         },  
         colors: ['#b0120a', '#7b1fa2', '#ffab91', '#d95f02'],  
         hAxis: {  
             title: 'Categories',  
             minValue: 0  
         },  
         vAxis: {  
             title: 'Product Count'  
         }  
      };  
      var chart;
      switch(chart_type) {
         case "line-chart":
            chart = new google.visualization.LineChart(document.getElementById('line_chart_div'));  
            break;
         case "pie-chart":
            chart = new google.visualization.PieChart(document.getElementById('pie_chart_div'));  
            break;
         case "area-chart":
            chart = new google.visualization.AreaChart(document.getElementById('area_chart_div'));  
            break;
         case "bar-chart":
            chart = new google.visualization.BarChart(document.getElementById('bar_chart_div'));  
            break;
         default:
            chart = new google.visualization.ColumnChart(document.getElementById('column_chart_div'));  
            break;
      }
      chart.draw(data, options);  
      return false;  
   }  
</script>  

If you point your browser to the home page, you should see five charts, namely: column, line, pie, area and bar charts.


Conclusion

I trust the above article helps you consider using Google Charts with ASP.NET MVC apps to visually display data.