Featured

Build Shopping Cart in ASP.NET 5

Last modified: June 19, 2021

E-Commerce websites are getting popular these days. One of them main functon on it, is the shopping cart. In the tutorial, we are going to learn how to implement shopping cart in asp.net 5

Step 1

Create an ASP.NET Core MVC application.

Step 2

Create a model file called Product in the Model folder

public class Product { public string Sku { get; set; } public string Name { get; set; } public decimal Price { get; set; } }

Create a model file called Product_Item in the Model folder. The SubTotal property calculates the sub total of a product by multiply of product price X quantity.

public class Product_Item { public Product Product { get; set; } public int Quantity { get; set; } private decimal _SubTotal; public decimal SubTotal { get { return _SubTotal; } set { _SubTotal = Product.Price * Quantity; } } }
Step 3

Create an Interfaces folder in the root level of your application and the create IProductService interface file in it. The GetProducts() method returns list of product whereas GetProduct() method return single product based on SKU input.

public interface IProductService { public IEnumerable<Product> GetProducts(); public Product GetProduct(string sku); }
Step 4

Create an Services folder in the root level of your application and the create ProductService class file in it. We inherit IProductService interface.

public class ProductService : IProductService { public Product GetProduct(string sku) { return GetProducts().Where(w => w.Sku == sku).FirstOrDefault(); } public IEnumerable<Product> GetProducts() { return new List<Product> { new Product{Sku = "sku1", Name="iphone 10", Price=800}, new Product{Sku = "sku2", Name="iphone 11", Price=900}, new Product{Sku = "sku3", Name="iphone 12", Price=1000}, new Product{Sku = "sku4", Name="iphone 12 Pro", Price=1200}, }; } }
Step 5

We are going to hold shopping cart data in Session variable, therefore We need to create following extension to set and get the value from a session. Create an Extensions folder in the root level of your application and the create SessionExtensions class file in it.

public static class SessionExtensions { public static void Set<T>(this ISession session, string key, T value) { session.SetString(key, JsonSerializer.Serialize(value)); } public static T Get<T>(this ISession session, string key) { var value = session.GetString(key); return value == null ? default : JsonSerializer.Deserialize<T>(value); } }
Step 6

We need to modify Startup.cs file to setup session and dependency injection (DI). In the ConfigureServices method, we need to add the following lines (services.AddSession(); and services.AddScoped<IProductService, ProductService>();)

public void ConfigureServices(IServiceCollection services) { services.AddDistributedMemoryCache(); services.AddSession(); //add this services.AddScoped<IProductService, ProductService>(); //add this services.AddControllersWithViews(); }

In the Configure method, we need to add this app.UseSession();

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseSession(); //add this app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
Step 7

Create a ProductController controller file with the template MVC Controller - Empty template.  We inject IProductService as dependency injection (DI) in the constructor.

public class ProductController : Controller { private readonly IProductService _productService; public ProductController(IProductService productService) { _productService = productService; } public IActionResult Index() { var products = _productService.GetProducts(); //get the list of products return View(products); //return to view } }
Step 8

We right-click on the Index method and choose Add View, and then Razor View - Empty which will generate a blank view. Copy the content below to this view.

@model IEnumerable<Shopping_Cart_ASP.NET_5.Models.Product> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.Name)</th> <th>@Html.DisplayNameFor(model => model.Price)</th> <th></th> </tr> </thead> <tbody> @foreach (var product in Model) //loop through the products { <tr> <td> @Html.DisplayFor(modelItem => product.Name) </td> <td> @Html.DisplayFor(modelItem => product.Price) </td> <td> @Html.ActionLink("Buy", "Buy", "Cart", new { sku = product.Sku }, new { @class = "btn btn-primary" }) </td> </tr> } </tbody> </table>

cart

Step 9

Create a CartController controller file with the template MVC Controller - Empty template.  We inject IProductService as dependency injection (DI) in the constructor.

In this controller, we have couple of the methods. We will go one by one.

private readonly IProductService _productService; public CartController(IProductService productService) { _productService = productService; }

In the index method, it gets "list of product item in cart" from session. If it is not null, we assign ViewBag.total the sum of total price (s.Quantity x s.Product.Price)

public IActionResult Index() { var cart = HttpContext.Session.Get<List<Product_Item>>("cart"); if (cart != null) { ViewBag.total = cart.Sum(s => s.Quantity * s.Product.Price); } else { cart = new List<Product_Item>(); ViewBag.total = 0; } return View(cart); }

_productService.GetProduct(sku); return the product information based on SKU. HttpContext.Session.Get<List<Product_Item>>("cart"); get the "list of products in cart" from session and assign to cart variable. cart.Add(new Product_Item { Product = product, Quantity = 1 }); add a product with quantity equals to 1. int index = cart.FindIndex(w => w.Product.Sku == sku); get index of a product in a cart variable. If index is -1, then is no existing product (i.e. buy product) and add to cart with quantity equals to 1, else it increment the existing quantity by 1. HttpContext.Session.Set<List<Product_Item>>("cart", cart); set the list to session.

public IActionResult Buy(string sku) { var product = _productService.GetProduct(sku); var cart = HttpContext.Session.Get<List<Product_Item>>("cart"); if(cart == null) //no item in the cart { cart = new List<Product_Item>(); cart.Add(new Product_Item { Product = product, Quantity = 1 }); } else { int index = cart.FindIndex(w => w.Product.Sku == sku); if (index != -1) //if item already in the { cart[index].Quantity++; //increment by 1 } else { cart.Add(new Product_Item { Product = product, Quantity = 1 }); } } HttpContext.Session.Set<List<Product_Item>>("cart", cart); return RedirectToAction("Index"); }

Get the index of the product and increment the quantity by 1.

public IActionResult Add(string sku) { var product = _productService.GetProduct(sku); var cart = HttpContext.Session.Get<List<Product_Item>>("cart"); int index = cart.FindIndex(w => w.Product.Sku == sku); cart[index].Quantity++; //increment by 1 HttpContext.Session.Set<List<Product_Item>>("cart", cart); return RedirectToAction("Index"); }

This method is to reduce the quantity. Get the index of project and reduce it quantity by 1. If it is the last item of a product then remove it.

public IActionResult Minus(string sku) { var product = _productService.GetProduct(sku); var cart = HttpContext.Session.Get<List<Product_Item>>("cart"); int index = cart.FindIndex(w => w.Product.Sku == sku); if(cart[index].Quantity == 1) //last item of a product { cart.RemoveAt(index); //remove it } else { cart[index].Quantity--; //reduce by 1 } HttpContext.Session.Set<List<Product_Item>>("cart", cart); return RedirectToAction("Index"); }

This method remove product from list by look up of index.

public IActionResult Remove(string sku) { var product = _productService.GetProduct(sku); var cart = HttpContext.Session.Get<List<Product_Item>>("cart"); int index = cart.FindIndex(w => w.Product.Sku == sku); cart.RemoveAt(index); HttpContext.Session.Set<List<Product_Item>>("cart", cart); return RedirectToAction("Index"); }
Step 10

We right-click on the Index method of CartController and choose Add View, and then Razor View - Empty which will generate a blank view. Copy the content below to this view.

We simply loop through the items in Shopping Cart. Here we have three functions; add quantity, minus quantity and remove the item.

@model IEnumerable<Shopping_Cart_ASP.NET_5.Models.Product_Item> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.Product.Name)</th> <th>@Html.DisplayNameFor(model => model.Product.Price)</th> <th>@Html.DisplayNameFor(model => model.Quantity)</th> <th>Sub-Total</th> <th></th> <th></th> </tr> </thead> <tbody> @foreach (var cart in Model) { <tr> <td> @Html.DisplayFor(modelItem => cart.Product.Name) </td> <td> @Html.DisplayFor(modelItem => cart.Product.Price) </td> <td> @Html.DisplayFor(modelItem => cart.Quantity) </td> <td> @Html.DisplayFor(modelItem => (cart.SubTotal)) </td> <td> @Html.ActionLink("+", "Add", "Cart", new { sku = cart.Product.Sku }, new { @class = "btn btn-primary" }) @Html.ActionLink("-", "Minus", "Cart", new { sku = cart.Product.Sku }, new { @class = "btn btn-danger" }) </td> <td> @Html.ActionLink("Remove", "Remove", "Cart", new { sku = cart.Product.Sku }, new { @class = "btn btn-danger" }) </td> </tr> } <tr> <td colspan="5" style="text-align:right"> Total: @ViewBag.total </td> </tr> </tbody> </table>

cart

Step 11

Finally we create hyperlink to product list and cart, we simply add below code to the _Layout file.

<li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-controller="Product" asp-action="Index">Product</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-controller="Cart" asp-action="Index">Cart</a> </li>