I am having trouble populating my pie chart using chart.js. The chart legend comes up but the values are undefined.
Cshml
@page
@model FinalProject.Pages.Exam.ReportModel
@{
Layout = null;
}
<h2>Letter Grade Report</h2>
<table>
<tr>
<th>Exam ID</th>
<th>Student ID</th>
<th>Score</th>
<th>Letter Grade</th>
</tr>
@foreach (var exam in Model.Exams)
{
<tr>
<td>@exam.ExamId</td>
<td>@exam.StudentID</td>
<td>@exam.Score</td>
<td>@FinalProject.Pages.Exam.ReportModel.CalculateLetterGrade(exam.Score)</td>
</tr>
}
</table>
<h2>Letter Grade Summary</h2>
<table>
<tr>
<th>Letter Grade</th>
<th>Total Count</th>
</tr>
@foreach (var gradeSummary in Model.GradeSummary)
{
<tr>
<td>@gradeSummary.LetterGrade</td>
<td>@gradeSummary.TotalCount</td>
</tr>
}
</table>
<!-- Add Chart.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<h2>Letter Grade Distribution (Pie Chart)</h2>
<div style="max-height:300px;">
<canvas id="gradeChart"></canvas>
</div>
<script>
let gradeData = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.GradeSummary));
const data = {
labels: gradeData.map(g => g.letterGrade),
datasets: [{
label: 'Grade Distribution',
data: gradeData.map(g => g.totalCount),
backgroundColor: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'],
hoverOffset: 4
}]
};
const config = {
type: 'pie',
data: data,
options: {
responsive: true,
maintainAspectRatio: false
}
};
new Chart(document.getElementById('gradeChart'), config);
</script>
Cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using School.DAL;
using System;
using System.Collections.Generic;
using System.Linq;
namespace FinalProject.Pages.Exam
{
public class ReportModel : PageModel
{
private readonly IExamAdapter _examAdapter;
public ReportModel(IExamAdapter examAdapter)
{
_examAdapter = examAdapter;
}
public List<School.DAL.Exam> Exams { get; set; }
public List<GradeSummary> GradeSummary { get; set; }
public void OnGet()
{
Exams = _examAdapter.GetAll().ToList();
// Calculate letter grades and generate summary
GradeSummary = CalculateGradeSummary(Exams);
}
private List<GradeSummary> CalculateGradeSummary(List<School.DAL.Exam> exams)
{
var gradeSummary = new List<GradeSummary>();
var gradeGroups = exams.GroupBy(e => CalculateLetterGrade(e.Score));
foreach (var group in gradeGroups)
{
gradeSummary.Add(new GradeSummary
{
LetterGrade = group.Key,
TotalCount = group.Count()
});
}
return gradeSummary;
}
public static string CalculateLetterGrade(string score)
{
if (int.TryParse(score, out int scoreValue))
{
if (scoreValue >= 90) return "A";
else if (scoreValue >= 80) return "B";
else if (scoreValue >= 70) return "C";
else if (scoreValue >= 60) return "D";
else return "F";
}
else
{
// Handle the case where score is not a valid integer (e.g., invalid input)
return "Invalid";
}
}
}
public class GradeSummary
{
public string LetterGrade { get; set; }
public int TotalCount { get; set; }
}
}
here is what is currently showing:

I tried changing up the script and am contemplating using Adapters instead of using the method im using but I feel like its an easy fix. The data all comes from CRUD operations on the site and that I added so the data is not static. Exam scores comes from another model that has its own CRUD operation (edit.cshtml, edit.cshtml.cs, delete.cshtml…..) and this page is used for reporting and charting exams scores