Thứ Tư, 20 tháng 9, 2017

Tạo giỏ hàng trực tuyến bằng Session trong ASP.NET MVC

Bài viết này hướng dẫn bạn tạo giỏ hàng trực tuyến bằng Session trong ASP.NET MVC (cụ thể là mình đang demo trên MVC 5). Chú ý rằng hướng dẫn có sử dụng LINQ và Entity Framework Database First.




Bước 1: Tạo class CartItem.cs như sau:

    public class CartItem
    {
        public string Hinh { get; set; }
        public int SanPhamID { get; set; }
        public string TenSanPham { get; set; }
        public int DonGia { get; set; }
        public int SoLuong { get; set; }
        public int ThanhTien
        {
            get
            {
                return SoLuong * DonGia;
            }
        }

    }

Bước 2: Tạo GioHangController và sửa nội dung trong action Index như sau:

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

        }

Nội dung trong action Index đơn giản là gán Session có key là giohang qua biến giohang rồi truyền qua view.

Bước 3: Tạo view Index.cshtml của GioHangController, view có 1 table chứa danh sách các CartItem nằm trong biến giohang được lấy từ action Index.

@model List<CartItem>
@{
    ViewBag.Title = "Giỏ hàng của bạn";
    Layout = "~/Views/Shared/_Layout.cshtml";
}


<h2>@ViewBag.Title</h2>

@if (Model == null || Model.Count == 0)
{
    <p class="text-info text-center">
        Giỏ hàng của bạn rỗng!
    </p>
}
else
{
    <div class="row">
        <div class="col-sm-12">
            <div class="table-responsive">
                <table class="table table-bordered">
                    <tr>
                        <th>Hình</th>
                        <th>Tên sản phẩm</th>
                        <th>Số lượng</th>
                        <th>Đơn giá</th>
                        <th>Thành tiền</th>
                        <th></th>
                    </tr>
                    @foreach (CartItem item in Model)
                {
                        <tr>
                            <td class="text-center"><img src="~/Content/Photos/SanPham/@item.Hinh" width="70" height="60" /> </td>
                            <td><a target="_blank" href="@Url.Action("ChiTiet", "SanPham", new { id = item.SanPhamID })"> @item.TenSanPham </a> </td>
                            <td>
                                <form action="@Url.Action("SuaSoLuong")" method="get">
                                    <input type="hidden" name="SanPhamID" value="@item.SanPhamID" />
                                    <input type="number" min="1" step="1" name="soluongmoi" value="@item.SoLuong" />
                                    <button type="submit" class="btn btn-primary btn-sm"> Cập nhật </button>
                                </form>
                            </td>
                            <td> @item.DonGia.ToString("#,##0").Replace(',', '.') VNĐ </td>
                            <td> @item.ThanhTien.ToString("#,##0").Replace(',', '.') VNĐ </td>

                            <td> <a href="@Url.Action("XoaKhoiGio",new { SanPhamID = item.SanPhamID})" 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.SoLuong) </td>
                        <td class="text-right">Tổng thành tiền:</td>
                        <td>@Model.Sum(m => m.ThanhTien).ToString("#,##0").Replace(',', '.') VNĐ </td>
                    </tr>
                </table>
            </div>
          
        </div>

    </div>

Ngoài ra trong view còn có lệnh if để kiểm tra trong trường hợp biến giohang là NULL hoặc không có item nào thì hiện thông báo rằng "giỏ hàng của bạn rỗng!".

Trong cột Số lượng mình còn tạo ra form để cho phép khách hàng sửa số lượng sản phẩm trong giỏ hàng của họ. Mỗi dòng trong table còn chứa liên kết cho phép Xóa sản phẩm khỏi giỏ hàng.

2 action SuaSoLuongXoaKhoiGio chúng ta sẽ tạo ở các bước bên dưới.

Bước 3: Tạo các nút "Đặt vào giỏ" ở bất kỳ view nào bạn muốn hiển thị để khách cho sản phẩm đấy vào giỏ hàng. Ví dụ đoạn lệnh sau hiển thị 1 nút có icon giỏ hàng cùng với thuộc tính href gọi đến action ThemVaoGio mà chúng ta sẽ tạo ở bước 4.

<a class="btn btn-success btn-sm" href="@Url.Action("ThemVaoGio", "GioHang", new { sanPhamID = Url.RequestContext.RouteData.Values["id"] })"> <span class="glyphicon glyphicon-shopping-cart"></span>  Thêm vào giỏ </a>




Bước 4: Tạo action ThemVaoGio có tham số SanPhamID và nội dung bên trong như sau:

        public RedirectToRouteResult ThemVaoGio(int SanPhamID)
        {
            if(Session["giohang"] == null) // Nếu giỏ hàng chưa được khởi tạo
            {
                Session["giohang"] = new List<CartItem>();  // Khởi tạo Session["giohang"] là 1 List<CartItem>
            }
           
            List<CartItem> giohang = Session["giohang"] 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 (giohang.FirstOrDefault(m => m.SanPhamID == SanPhamID) == null) // ko co sp nay trong gio hang
            {
                SanPham sp = db.SanPhams.Find(SanPhamID);  // tim sp theo sanPhamID

                CartItem newItem = new CartItem()
                {
                    SanPhamID = SanPhamID,
                    TenSanPham = sp.TenSanPham,
                    SoLuong = 1,
                    Hinh = sp.Hinh,
                    DonGia = sp.DonGia

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

                giohang.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 = giohang.FirstOrDefault(m => m.SanPhamID == SanPhamID);
                cardItem.SoLuong++;
            }
            
            // 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("ChiTiet", "SanPham", new { id = SanPhamID });
        }

Ý nghĩa các lệnh trong action mình đã chú thích rất rõ. Cơ bản là dùng LINQ để kiểm tra sản phẩm khách hàng chọn có tồn tại trong giỏ hàng không. Nếu không tồn tại thì thêm vào giỏ còn tồn tại rồi thì không thêm nữa mà chỉ tăng số lượng.

Bước 5: Tạo action SuaSoLuong có 2 tham số SanPhamIDsoluongmoi.

        public RedirectToRouteResult SuaSoLuong(int SanPhamID, int soluongmoi)
        {
            // tìm carditem muon sua
            List<CartItem> giohang = Session["giohang"] as List<CartItem>;
            CartItem itemSua = giohang.FirstOrDefault(m => m.SanPhamID == SanPhamID);
            if(itemSua != null)
            {
                itemSua.SoLuong = soluongmoi;
            }
            return RedirectToAction("Index");

        }

Action này thực hiện lấy ra CartItem cần sửa số lượng thông qua method FirstOrDefault sau đó cập nhật lại  thuộc tính SoLuong bằng với giá trị của tham số soluongmoi. Cuối cùng chuyển hướng về action Index để quay lại trang giỏ hàng.

Bước 6: Tạo action XoaKhoiGio có 1 tham số SanPhamID như sau:

public RedirectToRouteResult XoaKhoiGio(int SanPhamID)
        {
            List<CartItem> giohang = Session["giohang"] as List<CartItem>;
            CartItem itemXoa = giohang.FirstOrDefault(m => m.SanPhamID == SanPhamID);
            if (itemXoa != null)
            {
                giohang.Remove(itemXoa);
            }
            return RedirectToAction("Index");
        }

Action này cực kỳ đơn giản, chỉ việc tìm CartItem cần xóa và dùng method Remove để xóa khỏi Session["giohang"]

Thông qua 6 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. Ở bài viết sau mình sẽ hướng dẫn bạn tạo giỏ hàng bằng cơ sở dữ liệu thay vì Session, ưu điểm của cách làm này là không sợ giỏ hàng bị mất khi khách hàng lỡ tắt trình duyệt hoặc bị cúp điện đột ngột, máy bị reset bất chợt, ... Mọi thắc mắc bạn comment bên dưới bài viết để mình hỗ trợ nhé.


EmoticonEmoticon