Building an Expense Tracker with ASP.NET Core and Highcharts
Keeping track of your personal expenses is a critical step towards financial responsibility and achieving your monetary goals. An expense tracker application makes it easy to record your daily spending, view trends over time, stay within a budget, and make informed choices about your financial future.
In this article, we‘ll build a full-featured expense tracking application from scratch using ASP.NET Core, Entity Framework Core, and Highcharts. ASP.NET Core is a cross-platform, high-performance framework for building modern, cloud-enabled web applications. Entity Framework Core is an object-relational mapper that allows us to work with a database using .NET objects. Highcharts is a charting library written in pure JavaScript that makes it easy to add interactive, animated charts to web pages.
Project Setup
Let‘s start by creating a new ASP.NET Core Web App in Visual Studio. Choose the Web Application (Model-View-Controller) project template and select .NET 5.0 as the target framework.
Next, we‘ll add the necessary NuGet packages:
- Microsoft.EntityFrameworkCore.SqlServer: The database provider for Microsoft SQL Server
- Microsoft.EntityFrameworkCore.Tools: Tools for managing database migrations
Data Model
The core of our application is the Expense model class. It contains properties for all the info we want to track for a single expense:
public class Expense
{
public int Id { get; set; }
public DateTime Date { get; set; }
public string Description { get; set; }
public decimal Amount { get; set; }
public string Category { get; set; }
}
We‘ll also define a DbContext class to serve as a bridge between our application and the database:
public class ExpenseTrackerContext : DbContext
{
public DbSet<Expense> Expenses { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlServer("your connection string");
}
The DbSet property will allow us to query and save instances of the Expense class.
With the context in place, we can now create an initial migration to generate the database schema:
Add-Migration InitialCreate
Update-Database
Expense Controller
The ExpenseController class will handle all CRUD operations on expenses, as well as calculating summary data and stats for the dashboard.
Let‘s implement the Index action method to query all expenses:
public async Task<IActionResult> Index()
{
return View(await _context.Expenses.ToListAsync());
}
And here‘s the corresponding view to display the list of expenses:
@model IEnumerable<Expense>
<h2>Expenses</h2>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Description</th>
<th>Amount</th>
<th>Category</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>@Html.DisplayFor(modelItem => item.Date)</td>
<td>@Html.DisplayFor(modelItem => item.Description)</td>
<td>@Html.DisplayFor(modelItem => item.Amount)</td>
<td>@Html.DisplayFor(modelItem => item.Category)</td>
</tr>
}
</tbody>
</table>
We‘ll skip over the details of the Create, Edit, and Delete actions, as they follow a very similar pattern. You can refer to the complete source code for their implementations.
Expense Summary
To calculate summary statistics, we can use LINQ to group and aggregate the expense data. For example, here‘s how we can calculate the total expenses per category:
public async Task<IActionResult> ExpensesByCategory()
{
var expenses = await _context.Expenses
.GroupBy(e => e.Category)
.Select(g => new { Category = g.Key, TotalAmount = g.Sum(e => e.Amount) })
.ToListAsync();
return Json(expenses);
}
This will return the expense totals grouped by category in JSON format, which we can feed directly into a Highcharts pie chart.
Dashboard View
The dashboard view will contain several Highcharts components to visualize the expense data in different ways. Let‘s start with a basic column chart to show expenses over time:
<div id="expenseChart"></div>
@section Scripts {
<script src="https://code.highcharts.com/highcharts.js"></script>
<script>
$(function () {
$.getJSON("/Expense/ExpensesByMonth", function (data) {
$(‘#expenseChart‘).highcharts({
chart: {
type: ‘column‘
},
title: {
text: ‘Expenses by Month‘
},
xAxis: {
categories: data.map(e => e.Month)
},
yAxis: {
title: {
text: ‘Amount ($)‘
}
},
series: [{
name: ‘Expenses‘,
data: data.map(e => e.TotalAmount)
}]
});
});
});
</script>
}
This code makes an AJAX request to load the expense data grouped by month, then creates a column chart with the amounts. We can add more charts for other breakdowns like category, as well as a pie chart for the overall allocation.
To give the user more control, we can add a date range filter above the chart:
<form>
<label for="from">From:</label>
<input type="date" id="from" name="from">
<label for="to">To:</label>
<input type="date" id="to" name="to">
<input type="submit" value="Filter">
</form>
In the chart‘s click handler, we‘ll send the selected date range to the server and update the chart with the filtered data:
$(‘form‘).submit(function (e) {
e.preventDefault();
var from = $(‘#from‘).val();
var to = $(‘#to‘).val();
$.getJSON("/Expense/ExpensesByMonth?from=" + from + "&to=" + to, function (data) {
// Update chart with new data
});
});
Feel free to experiment with different chart types and configurations to build the ultimate expense dashboard!
Deployment
To deploy our application to a web server, we can publish it as a self-contained deployment:
dotnet publish -c Release -r win10-x64 --self-contained
This will generate an executable with all dependencies included, which we can copy to our server.
Next Steps
We‘ve built a solid foundation for an expense tracker, but there are always more features we can add:
- Support for multiple users with authentication and authorization
- Ability to attach receipts and invoices to expenses
- Recurring expense detection and prediction
- Budget planning and alerts
- Mobile app for on-the-go expense tracking
I encourage you to extend this application and make it your own. The principles and patterns we‘ve covered here – MVC, ORMs, data visualization – are applicable to a wide range of projects.
Take control of your finances and happy coding!