-->

Hướng dẫn tạo Shopping Cart với Session trong ASP.NET Core MVC

Tạo giỏ hàng luôn là vấn đề quan trọng nhất khi làm web bán hàng. Và với sự phát triển mạnh mẽ của thương mại điện tử, thì bán hàng online càng ngày càng xuất hiện nhiều. 

Và để làm quen với việc code Shopping Cart, mình sẽ hướng dẫn giỏ hàng cơ bản này, để bạn hiểu rõ hơn bản chất, và code được chức năng này, với việc dùng session trong ASP.NET Core MVC.


Trước tiên mình xin lưu ý trước là ví dụ này mình chưa kết nối với database, chỉ demo được chức năng giỏ hàng, sẽ có một bài viết về giỏ hàng với nghiệp vụ hoàn chỉnh ở bài sau. Ok chúng ta cùng tiến hành code nhé.

Tiến hành

Bước 1: Tạo project ASP.NET Core Web Application với tên là Cart. Demo

Bước 2: Chọn Web Application (Model - View - Controller).

Bước 3: Cài đặt các NuGet Package sau trong Cart.Demo:

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Relational
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools

Bước 4: Bổ Sung Configurations, các bạn vào Startup.cs thêm services.AddSession(); và app.UseSession(); như dưới:


Bước 5: Tạo folder tên là Entities, trong thư mục này tạo các class sau:

Item.cs

namespace Cart.Demo.Entities
{
    public class Item
    {
        public Product Product { get; set; }

        public int Quantity { get; set; }
    }
}

Product.cs


namespace Cart.Demo.Entities
{
    public class Product
    {
        public string Id { get; set; }

        public string Name { get; set; }

        public double Price { get; set; }

        public string Photo { get; set; }
    }
}

ProductModel.cs


using System.Collections.Generic;
using System.Linq;

namespace Cart.Demo.Entities
{
    public class ProductModel
    {
        private List<Product> products;

        public ProductModel()
        {
            this.products = new List<Product>() {
                new Product {
                    Id = "p01",
                    Name = "Balo chống gù lưng",
                    Price = 120000,
                    Photo = "item1.jpg"
                },
                new Product {
                    Id = "p02",
                    Name = "Mũ tai bèo hươu cao cổ",
                    Price = 320000,
                    Photo = "item2.jpg"
                },
                new Product {
                    Id = "p03",
                    Name = "Thắt lưng trẻ em",
                    Price = 110000,
                    Photo = "item3.jpg"
                },
                new Product {
                    Id = "p04",
                    Name = "Váy hồng đính nơ trẻ em",
                    Price = 99000,
                    Photo = "item4.jpg"
                }
            };
        }

        public List<Product> findAll()
        {
            return this.products;
        }

        public Product find(string id)
        {
            return this.products.Single(p => p.Id.Equals(id));
        }

    }
}

Bước 6: Trong folder Models, tạo class SessionHelper.cs với code sau:

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;

namespace Cart.Demo.Models
{
    public static class SessionHelper
    {
        public static void SetObjectAsJson(this ISession session, string key, object value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T GetObjectFromJson<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }
    }
}

Bước 7: Trong thư mục Controllers tạo các Controllers sau:

CartController.cs

using Cart.Demo.Entities;
using Cart.Demo.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;

namespace Cart.Demo.Controllers
{
    [Route("cart")]
    public class CartController : Controller
    {
        [Route("index")]
        public IActionResult Index()
        {
            var cart = SessionHelper.GetObjectFromJson<List<Item>>(HttpContext.Session, "cart");
            ViewBag.cart = cart;
            ViewBag.total = cart.Sum(item => item.Product.Price * item.Quantity);
            return View();
        }

        [Route("buy/{id}")]
        public IActionResult Buy(string id)
        {
            ProductModel productModel = new ProductModel();
            if (SessionHelper.GetObjectFromJson<List<Item>>(HttpContext.Session, "cart") == null)
            {
                List<Item> cart = new List<Item>();
                cart.Add(new Item { Product = productModel.find(id), Quantity = 1 });
                SessionHelper.SetObjectAsJson(HttpContext.Session, "cart", cart);
            }
            else
            {
                List<Item> cart = SessionHelper.GetObjectFromJson<List<Item>>(HttpContext.Session, "cart");
                int index = isExist(id);
                if (index != -1)
                {
                    cart[index].Quantity++;
                }
                else
                {
                    cart.Add(new Item { Product = productModel.find(id), Quantity = 1 });
                }
                SessionHelper.SetObjectAsJson(HttpContext.Session, "cart", cart);
            }
            return RedirectToAction("Index");
        }

        [Route("remove/{id}")]
        public IActionResult Remove(string id)
        {
            List<Item> cart = SessionHelper.GetObjectFromJson<List<Item>>(HttpContext.Session, "cart");
            int index = isExist(id);
            cart.RemoveAt(index);
            SessionHelper.SetObjectAsJson(HttpContext.Session, "cart", cart);
            return RedirectToAction("Index");
        }

        private int isExist(string id)
        {
            List<Item> cart = SessionHelper.GetObjectFromJson<List<Item>>(HttpContext.Session, "cart");
            for (int i = 0; i < cart.Count; i++)
            {
                if (cart[i].Product.Id.Equals(id))
                {
                    return i;
                }
            }
            return -1;
        }

    }
}

ProductController.cs

using Cart.Demo.Entities;
using Microsoft.AspNetCore.Mvc;

namespace Cart.Demo.Controllers
{
    public class ProductController : Controller
    {
        public ActionResult Index()
        {
            ProductModel productModel = new ProductModel();
            ViewBag.products = productModel.findAll();
            return View();
        }
    }
}

Bước 8: Bạn cần thêm giao diện cho danh sách sản phẩm và giỏ hàng, mình đã code sẵn các bạn tải về theo link với:

https://drive.google.com/file/d/1WnSX6NmVxT6w8AfxYi0flvAPUqbawP3X/view

Bước 9: Giải nén và copy cả file vừa rồi vào wwwroot:

Bước 10: Trong thư mục Views, bạn tạo các views sau:

Views/Product/Index.cshtml

@{
    Layout = null;
}


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sản phẩm</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Font Roboto, Lato -->
    <link href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i,900,900i|Roboto:400,400i,500,500i,700,700i,900,900i&display=swap" rel="stylesheet">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

    <link href="~/themeShoppingCart/style.css" rel="stylesheet" />
</head>
<body>
    <div class="container-fluid product-wrapper">
        <div class="container product-wrap">
            @foreach (var product in ViewBag.products)
            {
                <div class="product-item">
                    <a href="#" class="product-thumbnail">
                        <img src="~/themeShoppingCart/img/@product.Photo" class="img-thumb">
                    </a>
                    <h3 class="product-title">
                        <a href="#">@product.Name</a>
                        <span class="price item-price">@product.Price</span>
                    </h3>
                    <div class="product-action">
                        <a asp-controller="cart" asp-action="buy" asp-route-id="@product.Id" class="btn btn-addtocart">Thêm vào giỏ</a>
                    </div>
                </div>
            }
        </div>
    </div>

    <div class="credit">
        <p>Design and Coded by Ho Quoc Hieu - quochieu.com</p>
    </div>
</body>
</html>

Views/Cart/Index.cshtml

@{
    Layout = null;
}



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Giỏ hàng</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Font Roboto, Lato -->
    <link href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i,900,900i|Roboto:400,400i,500,500i,700,700i,900,900i&display=swap" rel="stylesheet">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

    <link href="~/themeShoppingCart/style.css" rel="stylesheet" />
</head>
<body>
    <div class="container-fluid cart-wrapper">
        <div class="container cart-wrap">
            <div class="cart-inner">
                <table class="table cart-table">
                    <thead>
                        <tr>
                            <th scope="col">ID</th>
                            <th scope="col">Image</th>
                            <th scope="col">Product Name</th>
                            <th scope="col">Price</th>
                            <th scope="col">Quantity</th>
                            <th scope="col">Sub Total</th>
                            <th scope="col">Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (var item in ViewBag.cart)
                        {
                            <tr>
                                <th scope="row">@item.Product.Id</th>
                                <td><img src="~/themeShoppingCart/img/@item.Product.Photo" class="table-img"></td>
                                <td><p class='table-item-name'>@item.Product.Name</p></td>
                                <td><span class='table-price'>120 000 đ</span></td>
                                <td>@item.Quantity</td>
                                <td><span class='table-sub-total'>@(item.Product.Price * item.Quantity)</span></td>
                                <td><a asp-controller="cart" asp-action="remove" asp-route-id="@item.Product.Id" class="btn btn-danger">Delete</a></td>
                            </tr>
                        }
                            <tr class="trsum">
                                <td colspan="5" style="text-align: right;">Sum</td>
                                <td colspan="2" style="text-align: left;">@ViewBag.total</td>
                            </tr>
                        </tbody>
                </table>
            </div>
            <a asp-controller="product" asp-action="index" class="con-shopping">← Tiếp tục mua sắm</a>
        </div>
        <div class="credit">
            <p>Design and Coded by Ho Quoc Hieu - quochieu.com</p>
        </div>
    </div>
</body>
</html>

Bước 11: Chạy project và xem kết quả:

Trang sản phẩm:

Khi thực hiện thao tác Thêm vào giỏ:

Lời kết

Các bước thực hiện rất dễ dàng thao tác, nhưng khuyến khích bạn code lại và nghiên cứu về nó.

Để sửa tên thông tin các sản phẩm, các bạn xem lại bước 5.

Và mình xin lưu ý là ví dụ này mình chưa kết nối với database, chỉ demo được chức năng giỏ hàng, sẽ có một bài viết về giỏ hàng với nghiệp vụ hoàn chỉnh ở bài sau. Hãy theo dõi blog để có các bài viết sắp tới nhé.

Nếu bạn gặp khó khăn khi không hiểu các bước thao tác tạo các cấu trúc, class, hãy xem hình dưới đây:



Mong bài viết hữu ích với bạn, chúc các bạn thành công.

By Quốc Hiếu

Có lẽ bạn thích?

1 comment

Post a Comment