ASP.NET - MVC - Xây dựng giỏ hàng

Xây dựng giỏ hàng

Đầu tiên, chúng ta sẽ cùng tìm hiểu Giỏ hàng trong website mua sm trc tuyến có ý nghĩa gì?

Khi bước vào siêu thị để mua hàng, đầu tiên bạn sẽ chọn “giỏ hàng hoặc “xe đy hàng.Trong quá trình mua sắm, bạn có thể chọn hàng cho vào giỏ, tăng giảm số lượng, thay đổi bằng loại hàng hóa khác hoặc bỏ lại một sản phẩm không ưng ý. Những sản phẩm trong giỏ hàng sẽ được lưu trữ tạm thời và được bỏ ra khi thanh toán.

Giỏ hàng trong website thương mại điện tử cũng vậy. Nó cho phép bạn thêm một loại sản phẩm vào giỏ hàng, loại bỏ sản phẩm khác hay tăng giảm số lượng của một sản phẩm nào đó. Sau khi thực hiện chức năng thanh toán, giỏ hàng của bạn sẽ quay về trạng thái rỗng (null).

Các bước xây dựng giỏ hàng:

  1. Tạo một project tên là Shopping Cart
  2. Xây dựng cấu trúc dữ liệu CartItem
  3. Tạo Model Product 
  4. Xây dựng Controller hiện thị danh sách sản phẩm
  5. Thêm mặt hàng vào giỏ hàng
  6. Cập nhật giỏ hàng hàng
  7. Xóa sản phẩm ra khỏi giỏ hàng

Tạo một project tên là Shopping Cart

Xây dựng cấu trúc CartItem

Giỏ hàng ta xây dựng nó là một danh sách List, chứa các mục trong giỏ hàng, mỗi mục là một đối tượng lớp CartItem, lớp đó như sau:

Trong Model chúng ta tạo class CartItem.cs:

 public class CartItem
    {
        public int Id { get; set; }
        [DisplayName("Tên sản phẩm")]
        public string Name { get; set; }

        public double Price { get; set; }

        public string Photo { get; set; }
        public int Amount { get; set; }
        public double Money
        {
            get
            {
                return Amount * Price;
            }
        }
    }

Tạo Model ProductModel

Tạo ra một lớp đơn giản biểu diễn các sản phẩm, đặt tên lớp là ProductModel.cs

public class ProductModel
    {
        private List<CartItem> products;

        public ProductModel()
        {
            this.products = new List<CartItem>() {
                new CartItem {
                    Id = 1,
                    Name = "Balo chống gù lưng",
                    Price = 120000,
                    Photo = "item1.jpg"
                },
                new CartItem {
                    Id = 2,
                    Name = "Mũ tai bèo hươu cao cổ",
                    Price = 320000,
                    Photo = "item2.jpg"
                },
                new CartItem {
                    Id = 3,
                    Name = "Thắt lưng trẻ em",
                    Price = 110000,
                    Photo = "item3.jpg"
                },
                new CartItem {
                    Id = 4,
                    Name = "Váy hồng đính nơ trẻ em",
                    Price = 99000,
                    Photo = "item4.jpg"
                },
                new CartItem {
                    Id = 5,
                    Name = "Áo Thun Cho Bé Tay Ngắn In Nhiều Họa Tiết Xinh xắn",
                    Price = 100000,
                    Photo = "item5.jpg"
                },
                new CartItem {
                    Id = 6,
                    Name = "Quần Short Jean Cho Bé Gái In Hình Sành Điệu",
                    Price = 120000,
                    Photo = "item6.jpg"
                },
                new CartItem {
                    Id = 7,
                    Name = "Quần Short Jean Lửng Cho Bé Gái Sành Điệu",
                    Price = 170000,
                    Photo = "item7.jpg"
                },
                new CartItem {
                    Id = 8,
                    Name = "Quần Short Jean Lửng Cho Bé Gái Sành Điệu",
                    Price = 200000,
                    Photo = "item8.jpg"
                },
                 new CartItem {
                    Id = 9,
                    Name = "Áo Thun Có Nón Bé Gái Tay Ngắn In Cô Bé Xinh Xắn",
                    Price = 200000,
                    Photo = "item9.jpg"
                },
            };
        }

        public List<CartItem> FindAll()
        {
            return this.products;
        }

        public CartItem FindProduct(int id)
        {
            return this.products.Single(p => p.Id.Equals(id));
        }
  
    }

Copy thư mục hình bỏ vào thư mục Content:

Download hình cho project

Controller hiện thị danh sách sản phẩm

Ta xây dựng Controller - HomeController hiện thị danh sách sản phẩm và các chức năng liên quan đến cart như đưa một sản phẩm vào giỏ hàng, xóa sản phẩm khỏi giỏ hàng ... Các chức năng đó thực hiện với các Action tương ứng như sau:

Controllers/HomeController.cs

public ActionResult Index()
        {
            ProductModel db = new ProductModel();
            return View(db.FindAll().ToList());
        }

Trang Index tương ứng với Action Index ở trên, hiện thị danh sách các sản phẩm, tại View Index.cshtml xây dựng như sau:

Views/Home/index.cshtml

@model List<ShoppingCart.Models.CartItem>
@{
    ViewData["Title"] = "Các sản phẩm";
}
<style>
    .glyphicon {
        margin-right: 5px;
    }

    .thumbnail {
        margin-bottom: 20px;
        padding: 0px;
        -webkit-border-radius: 0px;
        -moz-border-radius: 0px;
        border-radius: 0px;
    }

    .item.list-group-item {
        float: none;
        width: 100%;
        background-color: #fff;
        margin-bottom: 10px;
    }

        .item.list-group-item:nth-of-type(odd):hover, .item.list-group-item:hover {
            background: #428bca;
        }

        .item.list-group-item .list-group-image {
            margin-right: 10px;
        }

        .item.list-group-item .thumbnail {
            margin-bottom: 0px;
        }

        .item.list-group-item .caption {
            padding: 9px 9px 0px 9px;
        }

        .item.list-group-item:nth-of-type(odd) {
            background: #eeeeee;
        }

        .item.list-group-item:before, .item.list-group-item:after {
            display: table;
            content: " ";
        }

        .item.list-group-item img {
            float: left;
        }

        .item.list-group-item:after {
            clear: both;
        }

    .list-group-item-text {
        margin: 0 0 11px;
    }
</style>
<div class="container">
    <div class="well well-sm">
        <strong>Category Title</strong>
        <div class="btn-group">
            <a href="#" id="list" class="btn btn-default btn-sm">
                <span class="glyphicon glyphicon-th-list">
                </span>List
            </a> <a href="#" id="grid" class="btn btn-default btn-sm">
                <span class="glyphicon glyphicon-th"></span>Grid
            </a>
        </div>
    </div>
    <div id="products" class="row list-group">
        @foreach (var product in Model)
        {
            <div class="item  col-xs-4 col-lg-4">
                <div class="thumbnail">
                    <img class="group list-group-image" src="http://placehold.it/400x250/000/fff" alt="" />
                    <div class="caption">
                        <h4 class="group inner list-group-item-heading">
                            @product.Name
                        </h4>
                        <p class="group inner list-group-item-text">
                            <img src="~/Content/Images/@product.Photo" width="300px" height="150px">
                        </p>
                        <div class="row">
                            <div class="col-xs-12 col-md-6">
                                <p class="lead">
                                    <span class="text-muted">@(product.Price.ToString("n0")) VND</span>
                                </p>
                            </div>
                            <div class="col-xs-12 col-md-6">
                                <a class="btn btn-success" href="@Url.Action("AddToCart", "ShoppingCart", new { ProductId = product.Id})"> Đặt hàng</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            
        }

    </div>
</div>

Chạy cho kết quả:

Xây dựng chức năng thêm mặt hàng vào cart

Khi người dùng bấm vào Đặt hàng ở danh sách sản phẩm, thì nó sẽ chuyển đến Action AddToCart, có chức năng đưa sản phẩm đó vào Cart. Xây dựng Action đó như sau:

Controllers/ShoppingCartController.cs

 public RedirectToRouteResult AddToCart(int ProductId)
        {
            ProductModel db = new ProductModel();
            if (Session["ShoppingCart"] == null) // Nếu giỏ hàng chưa được khởi tạo
            {
                Session["ShoppingCart"] = new List<CartItem>();  // Khởi tạo Session["giohang"] là 1 List<CartItem>
            }

            List<CartItem> ShoppingCart = Session["ShoppingCart"] as List<CartItem>;  // Gán qua biến giohang dễ code

            // Kiểm tra xem sản phẩm khách đang chọn đã có trong giỏ hàng chưa

            if (ShoppingCart.FirstOrDefault(m => m.Id == ProductId) == null) // ko co sp nay trong gio hang
            {
                CartItem prodouct = db.FindProduct(ProductId);  // tim sp theo sanPhamID

                CartItem newItem = new CartItem()
                {
                    Id = ProductId,
                    Name = prodouct.Name,
                    Amount = 1,
                    Photo = prodouct.Photo,
                    Price = prodouct.Price

                };  // Tạo ra 1 CartItem mới

                ShoppingCart.Add(newItem);  // Thêm CartItem vào giỏ 
            }
            else
            {
                // Nếu sản phẩm khách chọn đã có trong giỏ hàng thì không thêm vào giỏ nữa mà tăng số lượng lên.
                CartItem cardItem = ShoppingCart.FirstOrDefault(m => m.Id == ProductId);
                cardItem.Amount++;
            }

            // Action này sẽ chuyển hướng về trang chi tiết sp khi khách hàng đặt vào giỏ thành công. Bạn có thể chuyển về chính trang khách hàng vừa đứng bằng lệnh return Redirect(Request.UrlReferrer.ToString()); nếu muốn.
            return RedirectToAction("Index", "ShoppingCart");
        }

Trang hiện thị Cart

Tương ứng với action Cart

  public ActionResult Index()
        {
            List<CartItem> ShoppingCart = Session["ShoppingCart"] as List<CartItem>;
            return View(ShoppingCart);

        }

Views/ShoppingCart/Index.cshtml

@model IEnumerable<ShoppingCart.Models.CartItem>

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@if (Model == null)
{
    <p class="text-info text-center">
        Giỏ hàng của bạn rỗng!
    </p>
}
else
{
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Photo)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Amount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Money)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            </td>
            <td>
                <img src="~/Content/Images/@item.Photo" width="170" height="160" />

            </td>
            <td>
                <form action="@Url.Action("UpdateAmount")" method="get">
                    <input type="hidden" name="ProductId" value="@item.Id" />
                    <input type="number" min="1" step="1" name="newAmount" value="@item.Amount" />
                    <button type="submit" class="btn btn-primary btn-sm"> Cập nhật </button>
                </form>

            </td>
            <td> @item.Price.ToString("#,##0").Replace(',', '.') VNĐ </td>
            

            <td> <a href="@Url.Action("RemoveItem",new { ProductId = item.Id})" onclick="return confirm('Bạn có chắc muốn xóa sản phẩm này?');" class="btn btn-danger btn-sm">Xóa</a> </td>

        </tr>
    }
    <tr>
        <td></td>
        <td class="text-right">Tổng số lượng:</td>
        <td> @Model.Sum(m => m.Amount) </td>
        <td class="text-right">Tổng thành tiền:</td>
        <td>@Model.Sum(m => m.Money).ToString("#,##0").Replace(',', '.') VNĐ </td>
    </tr>
</table>
}

Kết quả sau khi mua hàng

Hiển thị lại tiêu đề cột. Vào Model CartItem định nghĩa lại thuộc tính:

Cập nhật mặt hàng vào cart

Khi người dùng bấm vào Cập nhật ở danh sách sản phẩm, thì nó sẽ chuyển đến Action UpdateAmount, có chức năng cập nhật sản phẩm đó vào Cart. Xây dựng Action đó như sau:

Controllers/ShoppingCartController.cs

 public RedirectToRouteResult UpdateAmount(int ProductId, int newAmount)
        {
            // tìm carditem muon sua
            List<CartItem> ShoppingCart = Session["ShoppingCart"] as List<CartItem>;
            CartItem EditAmount = ShoppingCart.FirstOrDefault(m => m.Id == ProductId);
            if (EditAmount != null)
            {
                EditAmount.Amount = newAmount;
            }
            return RedirectToAction("Index");

        }
       

Xóa sản phẩm ra khỏi giỏ hàng

Khi người dùng bấm vào Xóa ở danh sách sản phẩm, thì nó sẽ chuyển đến Action RemoveItem, có chức năng xóa sản phẩm ra khỏi giỏ hàng. Xây dựng Action đó như sau:

Controllers/ShoppingCartController.cs

public RedirectToRouteResult RemoveItem(int ProductId)
        {
            List<CartItem> shoppingCart = Session["ShoppingCart"] as List<CartItem>;
            CartItem DelItem = shoppingCart.FirstOrDefault(m => m.Id == ProductId);
            if (DelItem != null)
            {
                shoppingCart.Remove(DelItem);
            }
            return RedirectToAction("Index");
        }

Thông qua các bước trên là bạn đã hoàn thành đầy đủ các chức năng cần thiết của 1 giỏ hàng trực tuyến bằng cách dùng đối tượng Session trong ASP.NET MVC

Hiện còn thiếu các chức năng

  1. Xóa toàn bộ sản phẩm ra khỏi giỏ hàng
  2. Tiếp tục mua hàng
  3. Thanh toán 

Các bạn có thể phát triển thêm