DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Building a RESTful Service Using ASP.NET Core and dotConnect for PostgreSQL
  • Working With dotConnect for Oracle in ASP.NET Core
  • Implementing Cache Dependency in ASP.NET Core
  • Working With dotConnect for SQL Server in ASP.NET Core

Trending

  • Understanding IEEE 802.11(Wi-Fi) Encryption and Authentication: Write Your Own Custom Packet Sniffer
  • How Kubernetes Cluster Sizing Affects Performance and Cost Efficiency in Cloud Deployments
  • Orchestrating Microservices with Dapr: A Unified Approach
  • How To Introduce a New API Quickly Using Quarkus and ChatGPT
  1. DZone
  2. Coding
  3. Frameworks
  4. ASP.NET Core: Expense Manager Using EF Core and Highcharts

ASP.NET Core: Expense Manager Using EF Core and Highcharts

In this article, we will be creating a personal expense manager using Asp.NET Core 2.1 and Entity Framework core Code first approach. An expense manager trac...

By 
Ankit Sharma user avatar
Ankit Sharma
·
Jul. 27, 18 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
24.4K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

In this article, we will be creating a personal expense manager using APS.NET Core 2.1 and the Entity Framework Core code first approach. An expense manager tracks your daily expenses and provides comparative charts to show expense summary. We are using modal dialog to handle user inputs and to show monthly and weekly expense summary charts using Highcharts. Hence, this application will be a Single Page Application (SPA) .

We will be using Visual Studio 2017 and SQL Server 2017 for our demo.

Let us look at the final application.

Prerequisites

  • Install .NET Core 2.1 SDK from here.
  • Install the latest version of Visual Studio 2017 from here.
  • SQL Server 2008 or above.

Source Code

Before proceeding, I would recommend you to get the source code from GitHub.

Create an ASP.NET Core Project

Open Visual Studio and select File >> New >> Project.

After selecting the project, a "New Project" dialog will open. Select .NET Core inside the Visual C# menu from the left panel.

Then, select "ASP.NET Core Web Application" from the available project types. Put the name of the project as ExpenseManager and press OK to create the ASP.NET Core Project.

After clicking on OK, a new dialog will open asking you to select the project template. You will see two drop-down menus at the top left of the template window. Select ".NET Core" and "ASP.NET Core 2.1" from these dropdowns. Then, select "Web application (Model-View-Controller)" template and press OK.

Adding the Model to the Application

Since we are using Entity Framework Code first approach, so first we will create our model class and then generate our database tables using the model.

Right click on Models folder and select Add >> Class. Name your class ExpenseReport.cs. This class will contain our Employee model properties.

Open ExpenseReport.cs file and put in the following code into it.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace ExpenseManager.Models
{
    public class ExpenseReport
    {
        [Key]
        public int ItemId { get; set; }
        [Required]
        public string ItemName { get; set; }

        [Required]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(10, 2)")]
        public decimal Amount { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        [Required]
        public DateTime ExpenseDate { get; set; } = DateTime.Now;

        [Required]
        public string Category { get; set; }
    }
}

We have used the [Key] attribute with ItemId to consider it as the primary key while creating the database table.

Creating the Database Table Using EF Core Code First Approach

In order to create our tables using the EF Core code first approach we need to install a few NuGet packages.

Navigate to Tools >> NuGet Package Manager >> Package Manager Console.

We have to install the package for the database provider that we are targeting, which is SQL Server in this case. Hence, run the following command:

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Since we are using Entity Framework Tools to create a table from the existing model, we will install the tools package as well. Hence, run the following command:

Install-Package Microsoft.EntityFrameworkCore.Tools

After the package installations are successful, we will create a dbcontext class. Add a file ExpenseDBContext.cs in the Modals folder and put in the following code into it:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ExpenseManager.Models
{
    public class ExpenseDBContext : DbContext
    {
        public virtual DbSet<ExpenseReport> ExpenseReport { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
                optionsBuilder.UseSqlServer("Your connection string");
            }
        }
    }
}

Do not forget to put in your own connection string (inside  " ").

We will create a dataset migration which is used to keep the database schema in sync with the model. There is no database at the moment, so the first migration will create it and add tables for the entities represented by the DbSet properties on the  ExpenseDBContext that we have created.

To create the dataset migration, navigate to the project folder and open the powershell window. Execute the following command in it.

dotnet ef  migrations add ExpenseMigration

Refer to the image below

This will create a folder named 'Migrations' into our project, which contains the code for the migration and a model snapshot. Refer to the image below:

Enter the following command in the Powershell window to execute the migration:

dotnet ef database update

Refer to the image below:

This will create the table "ExpenseReport" in to our database that we have mentioned in the connection string. You can observe that the column ItemId is the primary key here.

Hence, the database creation is completed successfully using the Entity Framework code first approach.

Adding the Data Access Layer to Our Application

Add a class file ExpensesDataAcessLayer.cs into the Modals folder and put the following code into it.

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ExpenseManager.Models
{
    public class ExpensesDataAcessLayer
    {
        ExpenseDBContext db = new ExpenseDBContext();
        public IEnumerable<ExpenseReport> GetAllExpenses()
        {
            try
            {
                return db.ExpenseReport.ToList();
            }
            catch
            {
                throw;
            }
        }

        // To filter out the records based on the search string 
        public IEnumerable<ExpenseReport> GetSearchResult(string searchString)
        {
            List<ExpenseReport> exp = new List<ExpenseReport>();
            try
            {
                exp = GetAllExpenses().ToList();
                return exp.Where(x => x.ItemName.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) != -1);
            }
            catch
            {
                throw;
            }
        }

        //To Add new Expense record       
        public void AddExpense(ExpenseReport expense)
        {
            try
            {
                db.ExpenseReport.Add(expense);
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        //To Update the records of a particluar expense  
        public int UpdateExpense(ExpenseReport expense)
        {
            try
            {
                db.Entry(expense).State = EntityState.Modified;
                db.SaveChanges();

                return 1;
            }
            catch
            {
                throw;
            }
        }

        //Get the data for a particular expense  
        public ExpenseReport GetExpenseData(int id)
        {
            try
            {
                ExpenseReport expense = db.ExpenseReport.Find(id);
                return expense;
            }
            catch
            {
                throw;
            }
        }

        //To Delete the record of a particular expense  
        public void DeleteExpense(int id)
        {
            try
            {
                ExpenseReport emp = db.ExpenseReport.Find(id);
                db.ExpenseReport.Remove(emp);
                db.SaveChanges();

            }
            catch
            {
                throw;
            }
        }

        // To calculate last six months expense
        public Dictionary<string, decimal> CalculateMonthlyExpense()
        {
            ExpensesDataAcessLayer objexpense = new ExpensesDataAcessLayer();
            List<ExpenseReport> lstEmployee = new List<ExpenseReport>();

            Dictionary<string, decimal> dictMonthlySum = new Dictionary<string, decimal>();

            decimal foodSum = db.ExpenseReport.Where
                (cat => cat.Category == "Food" && (cat.ExpenseDate > DateTime.Now.AddMonths(-7)))
                .Select(cat => cat.Amount)
                .Sum();

            decimal shoppingSum = db.ExpenseReport.Where
               (cat => cat.Category == "Shopping" && (cat.ExpenseDate > DateTime.Now.AddMonths(-7)))
               .Select(cat => cat.Amount)
               .Sum();

            decimal travelSum = db.ExpenseReport.Where
               (cat => cat.Category == "Travel" && (cat.ExpenseDate > DateTime.Now.AddMonths(-7)))
               .Select(cat => cat.Amount)
               .Sum();

            decimal healthSum = db.ExpenseReport.Where
               (cat => cat.Category == "Health" && (cat.ExpenseDate > DateTime.Now.AddMonths(-7)))
               .Select(cat => cat.Amount)
               .Sum();

            dictMonthlySum.Add("Food", foodSum);
            dictMonthlySum.Add("Shopping", shoppingSum);
            dictMonthlySum.Add("Travel", travelSum);
            dictMonthlySum.Add("Health", healthSum);

            return dictMonthlySum;
        }

        // To calculate last four weeks expense
        public Dictionary<string, decimal> CalculateWeeklyExpense()
        {
            ExpensesDataAcessLayer objexpense = new ExpensesDataAcessLayer();
            List<ExpenseReport> lstEmployee = new List<ExpenseReport>();

            Dictionary<string, decimal> dictWeeklySum = new Dictionary<string, decimal>();

            decimal foodSum = db.ExpenseReport.Where
                (cat => cat.Category == "Food" && (cat.ExpenseDate > DateTime.Now.AddDays(-7)))
                .Select(cat => cat.Amount)
                .Sum();

            decimal shoppingSum = db.ExpenseReport.Where
               (cat => cat.Category == "Shopping" && (cat.ExpenseDate > DateTime.Now.AddDays(-28)))
               .Select(cat => cat.Amount)
               .Sum();

            decimal travelSum = db.ExpenseReport.Where
               (cat => cat.Category == "Travel" && (cat.ExpenseDate > DateTime.Now.AddDays(-28)))
               .Select(cat => cat.Amount)
               .Sum();

            decimal healthSum = db.ExpenseReport.Where
               (cat => cat.Category == "Health" && (cat.ExpenseDate > DateTime.Now.AddDays(-28)))
               .Select(cat => cat.Amount)
               .Sum();

            dictWeeklySum.Add("Food", foodSum);
            dictWeeklySum.Add("Shopping", shoppingSum);
            dictWeeklySum.Add("Travel", travelSum);
            dictWeeklySum.Add("Health", healthSum);

            return dictWeeklySum;
        }
    }
}

This file will have methods to handle CRUD operations on our database. We are also calculating the last six months expense and last four weeks expense for each category.

Adding the Controller to the Application

Right click on Controllers folder and select Add >> New Item. An "Add New Item" dialog box will open. Select "ASP.NET Core" from the left panel, then select "Controller class" from templates panel, and put the name as ExpenseController.cs. Press OK.

This will create our controller, ExpenseController, inside theControllers folder. Open the ExpenseController.cs file and put in the following code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ExpenseManager.Models;
using Microsoft.AspNetCore.Mvc;

namespace ExpenseManager.Controllers
{
    public class ExpenseController : Controller
    {
        ExpensesDataAcessLayer objexpense = new ExpensesDataAcessLayer();
        public IActionResult Index(string searchString)
        {
            List<ExpenseReport> lstEmployee = new List<ExpenseReport>();
            lstEmployee = objexpense.GetAllExpenses().ToList();

            if (!String.IsNullOrEmpty(searchString))
            {
                lstEmployee = objexpense.GetSearchResult(searchString).ToList();
            }
            return View(lstEmployee);
        }

        public ActionResult AddEditExpenses(int itemId)
        {
            ExpenseReport model = new ExpenseReport();
            if (itemId > 0)
            {
                model = objexpense.GetExpenseData(itemId);
            }
            return PartialView("_expenseForm", model);
        }

        [HttpPost]
        public ActionResult Create(ExpenseReport newExpense)
        {
            if (ModelState.IsValid)
            {
                if (newExpense.ItemId > 0)
                {
                    objexpense.UpdateExpense(newExpense);
                }
                else
                {
                    objexpense.AddExpense(newExpense);
                }
            }
            return RedirectToAction("Index");
        }

        [HttpPost]
        public IActionResult Delete(int id)
        {
            objexpense.DeleteExpense(id);
            return RedirectToAction("Index");
        }

        public ActionResult ExpenseSummary()
        {
            return PartialView("_expenseReport");
        }

        public JsonResult GetMonthlyExpense()
        {
            Dictionary<string, decimal> monthlyExpense = objexpense.CalculateMonthlyExpense();
            return new JsonResult(monthlyExpense);
        }

        public JsonResult GetWeeklyExpense()
        {
            Dictionary<string, decimal> weeklyExpense = objexpense.CalculateWeeklyExpense();
            return new JsonResult(weeklyExpense);
        }
    }
}

The controller will have the methods that will call our data access layer methods to handle database operations.

Adding Views to the Application

We will create three view files:

  1. Index.cshtml: this view will display all the expense data and contains a search box to search for a particular item.
  2. _expenseForm.cshtml: this is a partial view, which contains the form to handle user inputs. This is used for both add and edit functionality and will be rendered in a modal dialog.
  3. _expenseReport.cshtml: this is also a partial view, which will show the expense summary in a bar chart using Highcharts. It is also rendered as a modal dialog.

Index View

To create the view file, right click on the Index method in our controller and select "Add View..." This will open an "Add MVC View" dialog box. Set the name of view as 'Index' and click Add. Make sure that the "Create as a partial view" check box is not checked. Refer to the image below:

This will create the Index.cshtml file inside "Expense" folder under the Views folder. Open Index.cshtml file and put in the following code:

@model IEnumerable<ExpenseManager.Models.ExpenseReport>

@{
    ViewData["Title"] = "Personal Expense Manager";
}
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.css" rel="stylesheet">

<h2>Personal Expense Manager</h2>
<br />
<div>
    <div style="float:left">
        <button class="btn btn-primary" onclick="AddEditExpenses(0)">Add Expense</button>
        <button class="btn btn-success" onclick="ReportExpense()">Expense Report</button>
    </div>
    <div style="float:right; width:40%;">
        <form asp-controller="Expense" asp-action="Index" class="form-group">
            <div class="col-sm-6">
                <input class="form-control" type="text" name="SearchString" placeholder="Search">
            </div>
            <button type="submit" class="btn btn-default btn-info">Filter</button>
        </form>
    </div>
</div>
<br />
<br />
<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.ItemId)</th>
            <th>@Html.DisplayNameFor(model => model.ItemName)</th>
            <th>@Html.DisplayNameFor(model => model.Amount)</th>
            <th>@Html.DisplayNameFor(model => model.ExpenseDate)</th>
            <th>@Html.DisplayNameFor(model => model.Category)</th>
            <th>Action Item</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>@Html.DisplayFor(modelItem => item.ItemId)</td>
                <td>@Html.DisplayFor(modelItem => item.ItemName)</td>
                <td>@Html.DisplayFor(modelItem => item.Amount)</td>
                <td>@Html.DisplayFor(modelItem => item.ExpenseDate)</td>
                <td>@Html.DisplayFor(modelItem => item.Category)</td>
                <td>
                    <button class="btn btn-default" onclick="AddEditExpenses(@item.ItemId)">Edit</button>
                    <button class="btn btn-danger" onclick="DeleteExpense(@item.ItemId)">Delete</button>
                </td>
            </tr>
        }
    </tbody>
</table>

<div class="modal fade" id="expenseFormModel" role="dialog">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <a href="#" class="close" data-dismiss="modal">&times;</a>
                <h3 id="title" class="modal-title">Add Expense</h3>
            </div>
            <div class="modal-body" id="expenseFormModelDiv">
            </div>
        </div>
    </div>
</div>

<div class="modal fade" id="expenseReportModal" role="dialog">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <a href="#" class="close" data-dismiss="modal">&times;</a>
                <h3 class="modal-title">Expense Report</h3>
            </div>
            <div class="modal-body" id="expenseReportModalDiv">
            </div>
        </div>
    </div>
</div>

<script>

    var AddEditExpenses = function (itemId) {
        var url = "/Expense/AddEditExpenses?itemId=" + itemId;
        if (itemId > 0)
            $('#title').html("Edit Expense");

        $("#expenseFormModelDiv").load(url, function () {
            $("#expenseFormModel").modal("show");

        });

        $('#expenseFormModel').on('shown.bs.modal', function () {

            $('#calender-container .input-group.date').datepicker({
                todayBtn: true,
                calendarWeeks: true,
                todayHighlight: true,
                autoclose: true,
                container: '#expenseFormModel modal-body'
            });

        });
    }

    var ReportExpense = function () {
        var url = "/Expense/ExpenseSummary";

        $("#expenseReportModalDiv").load(url, function () {
            $("#expenseReportModal").modal("show");
        })
    }

    var DeleteExpense = function (itemId) {

        var ans = confirm("Do you want to delete item with Item Id: " + itemId);

        if (ans) {
            $.ajax({
                type: "POST",
                url: "/Expense/Delete/" + itemId,
                success: function () {
                    window.location.href = "/Expense/Index";
                }
            })
        }
    }
</script>

<script>

    $('body').on('click', "#btnSubmit", function () {
        var myformdata = $("#expenseForm").serialize();

        $.ajax({
            type: "POST",
            url: "/Expense/Create",
            data: myformdata,
            success: function () {
                $("#myModal").modal("hide");
                window.location.href = "/Expense/Index";
            },
            error: function (errormessage) {
                alert(errormessage.responseText);
            }
        })
    })
</script>

Let us understand this code. At the top we have included Bootstrap and jQuery references. After that, we have added two buttons for adding a new expense and for creating the expense summary. We have also included a form containing a search box to filter out the records. On clicking the "Filter" button, the form is submitted and it invokes the Index method in our controller which will return the items matching the search criteria. The search functionality is provided only on an item's name field.

We are using a table to display all the expense records in our database and each record has two corresponding action buttons - Edit and Delete.

We have also created two modal dialogs, one for adding/editing the expense data and another for displaying the expense summary report.

In the script section, we have defined the AddEditExpenses function. This function will be invoked when the "Add Expense" or "Edit" button is clicked. We are passing the itemId as a parameter in this method. If the "ItemId" value is not set then it is considered to be an Add function and if the "ItemId" is set then it acts as an Edit function. We will call AddEditExpensesin our controller which will return the partial view_expenseForm and bind it to the ExpenseReport model. The modal will be empty for "Add" calls and contain the expense item data in case of "Edit" calls. Since we are using the Bootstrap datepicker to select the expense date, the datepicker properties are set when  the modal dialog loads.

The  ReportExpense function will call the ExpenseSummary method in our controller, which will return the partial view_expenseReport to be displayed as a modal dialog. This partial view will display the monthly and weekly expense summary chart using Highcharts.

The DeleteExpense function is used to delete the record of a particular expense. This will invoke the Delete method in our controller to remove the expense record from our database.

We are also using dynamic binding to bind the submit event of  the expenseForm modal. This form is defined in the_expenseForm.cshtml view. Upon submitting the  form, we are invoking an Ajax call to the Create method in our controller class. Since we are using the same form for both Edit and Add functionalities, we need to distinguish between them using the ItemId value. In the Create method of controller, we will check if the ItemId is set, then we will invoke the  UpdateExpense method, or else invoke the  AddExpense method. After successfully submitting, we will close the modal and redirect t theo Index view to show the updated list of expenses.

ExpenseForm View

This is a partial view that will be displayed in a modal dialog after clicking the "Add Expense" button in the Index view.

To create the view file, right-click anywhere inside our controller file and select "Add View." This will open an "Add MVC View" dialog box. Put in the name of view as "_expenseForm" and click Add. Make sure that "Create as a partial view" check box is selected. Refer to the image below:

Open the "_expenseForm.cshtml file" and put the following code in it:

@model ExpenseManager.Models.ExpenseReport

<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/js/bootstrap-datepicker.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.css" rel="stylesheet">

<div>
    <div class="row">
        <div class="col-md-8">
            <form id="expenseForm">
                <input type="hidden" asp-for="ItemId" />
                <div class="form-group">
                    <label asp-for="ItemName" class="control-label"></label>
                    <input asp-for="ItemName" class="form-control" />
                </div>
                <div class="form-group">
                    <label asp-for="Category" class="control-label"></label>
                    <select asp-for="Category" class="form-control">
                        <option value="">-- Select Category --</option>
                        <option value="Food">Food</option>
                        <option value="Shopping">Shopping</option>
                        <option value="Travel">Travel</option>
                        <option value="Health">Health</option>
                    </select>
                </div>
                <div class="form-group">
                    <label asp-for="Amount" class="control-label"></label>
                    <input asp-for="Amount" class="form-control" />
                </div>
                <div class="form-group" id="calender-container">
                    <label asp-for="ExpenseDate" class="control-label"></label>
                    <div class="input-group date">
                        <input asp-for="ExpenseDate" type="text" class="form-control"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
                    </div>
                </div>
                <div class="form-group">
                    <button type="button" id="btnSubmit" class="btn btn-block btn-info">Save</button>
                </div>
            </form>
        </div>
    </div>
</div>

At the top, we are including the CDN reference to the bootstrap-datepicker so that we can use it in our modal dialog. Then we have a form element, which binds to our modal. We also have a submit button which will post the form data to the Create method in our controller using an Ajax call.

ExpenseReport View

This is a partial view that is displayed in the modal dialog after clicking the "Expense Report" button in Index view.

Create a new partial view, "_expenseReport.cshtml", and put in the following code in it.

<script src="https://code.highcharts.com/highcharts.js"></script>

<button id="btnMonthlyReport" class="btn btn-info">Monthly Report</button>
<button id="btnWeeklyReport" class="btn btn-warning">Weekly Report</button>
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto">

</div>

<script>

    $(document).ready(function () {
        $("#btnWeeklyReport").click(function () {
            var titleMessage = "Expenses in last four weeks is : ";

            $.ajax({
                type: "GET",
                url: "/Expense/GetWeeklyExpense",
                contentType: "application/json",
                dataType: "json",
                success: function (result) {
                    var keys = Object.keys(result);
                    var weeklydata = new Array();
                    var totalspent = 0.0;
                    for (var i = 0; i < keys.length; i++) {
                        var arrL = new Array();
                        arrL.push(keys[i]);
                        arrL.push(result[keys[i]]);
                        totalspent += result[keys[i]];
                        weeklydata.push(arrL);
                    }
                    createCharts(weeklydata, titleMessage, totalspent.toFixed(2));
                }
            })
        })

        $("#btnMonthlyReport").click(function () {
            var titleMessage = "Expenses in last six months is : ";

            $.ajax({
                type: "GET",
                url: "/Expense/GetMonthlyExpense",
                contentType: "application/json",
                dataType: "json",
                success: function (result) {
                    var keys = Object.keys(result);
                    var monthlydata = new Array();
                    var totalspent = 0.0;
                    for (var i = 0; i < keys.length; i++) {
                        var arrL = new Array();
                        arrL.push(keys[i]);
                        arrL.push(result[keys[i]]);
                        totalspent += result[keys[i]];
                        monthlydata.push(arrL);
                    }
                    createCharts(monthlydata, titleMessage, totalspent.toFixed(2));
                }
            })
        })
    })

    function createCharts(sum, titleText, totalspent) {
        Highcharts.chart('container', {
            chart: {
                type: 'column'
            },
            title: {
                text: titleText + ' ' + totalspent
            },
            xAxis: {
                type: 'category',
                labels: {
                    rotation: -45,
                    style: {
                        fontSize: '13px',
                        fontFamily: 'Verdana, sans-serif'
                    }
                }
            },
            yAxis: {
                min: 0,
                title: {
                    text: 'Money spent'
                }
            },
            legend: {
                enabled: false
            },
            tooltip: {
                pointFormat: 'Total money spent: <b>{point.y:.2f} </b>'
            },
            series: [{
                type: 'column',
                data: sum,
            }]
        });
    }

</script>

At the top, we have included the CDN reference to Highcharts. We have also provided two buttons to view monthly reports for the last six months and weekly reports for the last four weeks. The report will be generated as a bar chart to provide a comparative study of expense summaries.

When we click the weekly report button, we will invoke the  GetWeeklyExpense method of our controller that will return the data in JSON format and we will pass this to the createCharts function to create the weekly expense bar chart using Highcharts.

Similarly, we will invoke the GetMonthlyExpense method of our controller when we click on the "Monthly Report" button and pass the JSON result to the  createCharts function to create the monthly expense bar chart using Highcharts.

Configure Route URL

Open the Startup.cs file to set the format for routing. Scroll down to the app.UseMvc method, where you can set the route URL.

Make sure that your route URL is set like this:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Expense}/{action=Index}");
});

This URL pattern sets ExpenseController as the default controller and the Index method as the default action method. Default route parameters do not need to be present in the URL path for a match. If we do not append any controller name in the URL then it will take ExpenseController as the default controller and the Index method of ExpenseController as the default action method. Similarly, if we only append "/Expense" to the URL, it will navigate to the Index action method of the Expense controller.

Execution Demo

Press F5 to launch the application. You should see a page similar to the one shown below.

Here we have the "Add Expense" button to add a new expense report. The "Expense Report" button will open a dialog box to show the bar chart for monthly and weekly expense data. On the top right corner, we have a search box to search the records using the item name.

Look at the below Gif for the demo of the application.

Conclusion

We created a personal expense manager application using ASP.NET Core and Entity Framework Core with the help of Visual Studio 2017 and SQL Server 2017. We have also used Highcharts to create a bar chart for monthly and weekly expense summaries.

Please download the source code from GitHub and play around to get a better understanding.

You can read my other articles on ASP .NET Core here.

Entity Framework Database ASP.NET ASP.NET Core Highcharts

Published at DZone with permission of Ankit Sharma, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building a RESTful Service Using ASP.NET Core and dotConnect for PostgreSQL
  • Working With dotConnect for Oracle in ASP.NET Core
  • Implementing Cache Dependency in ASP.NET Core
  • Working With dotConnect for SQL Server in ASP.NET Core

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!