購物車

作者 :Erik Reitan

下載 Wingtip Toys 範例專案 (C#) 下載電子書 (PDF)

本教學課程系列將教導您使用 ASP.NET 4.5 和 Microsoft Visual Studio Express 2013 for Web 建置 ASP.NET Web Forms應用程式的基本概念。 具有C# 原始程式碼的Visual Studio 2013專案隨附于本教學課程系列。

本教學課程說明將購物車新增至 Wingtip Toys 範例 ASP.NET Web Forms應用程式所需的商務邏輯。 本教學課程是以上一個教學課程「顯示資料項目和詳細資料」為基礎,並屬於 Wingtip Toy Store 教學課程系列。 當您完成本教學課程時,範例應用程式的使用者將能夠在其購物車中新增、移除和修改產品。

您將學到什麼:

  1. 如何建立 Web 應用程式的購物車。
  2. 如何讓使用者將專案新增至購物車。
  3. 如何新增 GridView 控制項以顯示購物車詳細資料。
  4. 如何計算及顯示訂單總計。
  5. 如何移除和更新購物車中的專案。
  6. 如何包含購物車計數器。

本教學課程中的程式碼功能:

  1. Entity Framework Code First
  2. 資料註釋
  3. 強型別資料控制項
  4. 模型繫結

建立購物車

稍早在本教學課程系列中,您已新增頁面和程式碼,以檢視資料庫中的產品資料。 在本教學課程中,您將建立購物車來管理使用者有興趣購買的產品。 即使使用者未註冊或登入,使用者還是能夠流覽專案並將其新增至購物車。 若要管理購物車存取權,您會在第一次存取購物車時,使用全域唯一識別碼 (GUID) ,將唯 ID 一識別碼指派給使用者。 您將使用 ASP.NET 會話狀態來儲存此 ID 專案。

注意

ASP.NET 會話狀態是儲存使用者特定資訊的便利位置,會在使用者離開網站之後過期。 雖然誤用會話狀態可能會對較大的網站造成效能影響,但對會話狀態的輕量使用適用于示範用途。 Wingtip Toys 範例專案示範如何在沒有外部提供者的情況下使用會話狀態,其中會話狀態會儲存在裝載網站的網頁伺服器上。 對於提供應用程式多個實例的較大網站,或針對在不同伺服器上執行多個應用程式實例的網站,請考慮使用 Windows Azure 快取服務。 此快取服務提供位於網站外部的分散式快取服務,並解決使用進程內會話狀態的問題。 如需詳細資訊,請參閱 如何搭配 Windows Azure 網站使用 ASP.NET 會話狀態

將 CartItem 新增為模型類別

稍早在本教學課程系列中,您會在Models資料夾中建立 Category 和 類別,以定義類別和 Product 產品資料的架構。 現在,新增 類別以定義購物車的架構。 稍後在本教學課程中,您將新增類別來處理資料表的資料存取 CartItem 。 此類別會供應商業規則,以新增、移除和更新購物車中的專案。

  1. 以滑鼠右鍵按一下Models資料夾,然後選取 [新增- >新增專案]。

    購物車 - 新增專案

  2. [ 加入新項目 ] 對話方塊隨即出現。 選取 [程式碼],然後選取 [ 類別]。

    購物車 - 新增專案對話方塊

  3. 將此新類別命名為 CartItem.cs

  4. 按一下 [新增] 。
    新的類別檔案會顯示在編輯器中。

  5. 使用下列程式碼來取代預設程式碼:

    using System.ComponentModel.DataAnnotations;
    
    namespace WingtipToys.Models
    {
        public class CartItem
        {
            [Key]
            public string ItemId { get; set; }
    
            public string CartId { get; set; }
    
            public int Quantity { get; set; }
    
            public System.DateTime DateCreated { get; set; }
    
            public int ProductId { get; set; }
    
            public virtual Product Product { get; set; }
    
        }
    }
    

類別 CartItem 包含架構,該架構會定義使用者新增至購物車的每個產品。 此類別類似于您稍早在本教學課程系列中建立的其他架構類別。 根據慣例,Entity Framework Code First 預期資料表的主鍵 CartItem 會是 CartItemIdID 。 不過,程式碼會使用資料批註 [Key] 屬性覆寫預設行為。 KeyItemId 屬性的屬性會 ItemID 指定屬性是主鍵。

屬性 CartIdID 指定要購買之專案相關聯之使用者的 。 您將新增程式碼,以在使用者存取購物車時建立此使用者 ID 。 這 ID 也會儲存為 ASP.NET 會話變數。

更新產品內容

除了新增 CartItem 類別之外,您還需要更新管理實體類別的資料庫內容類別別,並提供資料庫的資料存取權。 若要這樣做,您會將新建立 CartItem 的模型類別新增至 ProductContext 類別。

  1. 方案總管中,尋找並開啟Models資料夾中的ProductCoNtext.cs檔案。

  2. 將醒目提示的程式碼新增至 ProductCoNtext.cs 檔案,如下所示:

    using System.Data.Entity;
     
    namespace WingtipToys.Models
    {
        public class ProductContext : DbContext
        {
            public ProductContext()
                : base("WingtipToys")
            {
            }
     
            public DbSet<Category> Categories { get; set; }
            public DbSet<Product> Products { get; set; }
            public DbSet<CartItem> ShoppingCartItems { get; set; }
        }
    }
    

如本教學課程系列先前所述, ProductCoNtext.cs 檔案中的程式碼會新增 System.Data.Entity 命名空間,讓您能夠存取 Entity Framework 的所有核心功能。 此功能包含使用強型別物件來查詢、插入、更新和刪除資料的功能。 類別 ProductContext 會新增對新加入 CartItem 之模型類別的存取權。

管理購物車商務邏輯

接下來,您將在新的Logic資料夾中建立 ShoppingCart 類別。 類別 ShoppingCart 會處理資料表的資料存取 CartItem 。 類別也會包含商務邏輯,以新增、移除和更新購物車中的專案。

您將新增的購物車邏輯將包含管理下列動作的功能:

  1. 將專案新增至購物車
  2. 從購物車移除專案
  3. 取得購物車識別碼
  4. 從購物車擷取專案
  5. 總計所有購物車專案的數量
  6. 更新購物車資料

購物車頁面 (ShoppingCart.aspx) 和購物車類別將一起使用,以存取購物車資料。 購物車頁面會顯示使用者新增至購物車的所有專案。 除了購物車頁面和類別之外,您將建立頁面 (AddToCart.aspx) ,將產品新增至購物車。 您也會將程式碼新增至 ProductList.aspx 頁面和 ProductDetails.aspx 頁面,以提供 AddToCart.aspx 頁面的連結,讓使用者可以將產品新增至購物車。

下圖顯示使用者將產品新增至購物車時所發生的基本程式。

購物車 - 新增至購物車

當使用者按一下ProductList.aspx頁面或ProductDetails.aspx頁面上的 [新增至購物車] 連結時,應用程式會流覽至AddToCart.aspx頁面,然後自動流覽至ShoppingCart.aspx頁面。 AddToCart.aspx頁面會呼叫 ShoppingCart 類別中的 方法,將選取產品新增至購物車。 [ShoppingCart.aspx] 頁面會顯示已新增至購物車的產品。

建立購物車類別

類別 ShoppingCart 會新增至應用程式中的個別資料夾,因此模型 (Models 資料夾) 、頁面 (根資料夾) 和邏輯 (Logic 資料夾) 之間會有清楚的差異。

  1. 方案總管中,以滑鼠右鍵按一下WingtipToys專案,然後選取 [新增>資料夾]。 將新資料夾命名為 Logic

  2. 以滑鼠右鍵按一下[邏輯] 資料夾,然後選取 [新增- >新增專案]。

  3. 新增名為 ShoppingCartActions.cs的新類別檔案。

  4. 使用下列程式碼來取代預設程式碼:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    
    namespace WingtipToys.Logic
    {
      public class ShoppingCartActions : IDisposable
      {
        public string ShoppingCartId { get; set; }
    
        private ProductContext _db = new ProductContext();
    
        public const string CartSessionKey = "CartId";
    
        public void AddToCart(int id)
        {
          // Retrieve the product from the database.           
          ShoppingCartId = GetCartId();
    
          var cartItem = _db.ShoppingCartItems.SingleOrDefault(
              c => c.CartId == ShoppingCartId
              && c.ProductId == id);
          if (cartItem == null)
          {
            // Create a new cart item if no cart item exists.                 
            cartItem = new CartItem
            {
              ItemId = Guid.NewGuid().ToString(),
              ProductId = id,
              CartId = ShoppingCartId,
              Product = _db.Products.SingleOrDefault(
               p => p.ProductID == id),
              Quantity = 1,
              DateCreated = DateTime.Now
            };
    
            _db.ShoppingCartItems.Add(cartItem);
          }
          else
          {
            // If the item does exist in the cart,                  
            // then add one to the quantity.                 
            cartItem.Quantity++;
          }
          _db.SaveChanges();
        }
    
        public void Dispose()
        {
          if (_db != null)
          {
            _db.Dispose();
            _db = null;
          }
        }
    
        public string GetCartId()
        {
          if (HttpContext.Current.Session[CartSessionKey] == null)
          {
            if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
            {
              HttpContext.Current.Session[CartSessionKey] = HttpContext.Current.User.Identity.Name;
            }
            else
            {
              // Generate a new random GUID using System.Guid class.     
              Guid tempCartId = Guid.NewGuid();
              HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString();
            }
          }
          return HttpContext.Current.Session[CartSessionKey].ToString();
        }
    
        public List<CartItem> GetCartItems()
        {
          ShoppingCartId = GetCartId();
    
          return _db.ShoppingCartItems.Where(
              c => c.CartId == ShoppingCartId).ToList();
        }
      }
    }
    

方法 AddToCart 可讓根據產品 ID 將個別產品包含在購物車中。 產品會新增至購物車,或者如果購物車已經包含該產品的專案,則會遞增數量。

方法 GetCartId 會傳回使用者的購物車 ID 。 購物車 ID 是用來追蹤使用者在其購物車中擁有的專案。 如果使用者沒有現有的購物車 ID ,則會為其建立新的購物車 ID 。 如果使用者以已註冊的使用者身分登入,購物車 ID 會設定為其使用者名稱。 不過,如果使用者未登入,購物車 ID 會設定為唯一值, (GUID) 。 GUID 可確保根據會話,為每個使用者建立一個購物車。

方法 GetCartItems 會傳回使用者的購物車專案清單。 稍後在本教學課程中,您會看到模型系結是用來使用 GetCartItems 方法在購物車中顯示購物車專案。

建立增益集購物車功能

如先前所述,您將建立名為 AddToCart.aspx 的處理頁面,以用來將新產品新增至使用者的購物車。 此頁面會在您剛才建立的 類別中 ShoppingCart 呼叫 AddToCart 方法。 AddToCart.aspx頁面預期產品 ID 已傳遞給它。 在 類別中 ShoppingCart 呼叫 AddToCart 方法時,將會使用此產品 ID

注意

您將修改此頁面的程式碼後置 (AddToCart.aspx.cs) ,而不是 addToCart.aspx) 的頁面 (UI。

若要建立 Add-To-Cart 功能:

  1. 方案總管中,以滑鼠右鍵按一下WingtipToys專案,然後按一下 [新增- >新增專案]。
    [ 加入新項目 ] 對話方塊隨即出現。

  2. 將標準新頁面 (Web Form) 新增至名為 AddToCart.aspx的應用程式。

    購物車 - 新增 Web 表單

  3. 方案總管中,以滑鼠右鍵按一下AddToCart.aspx頁面,然後按一下 [檢視程式碼]。 AddToCart.aspx.cs程式碼後置檔案會在編輯器中開啟。

  4. 以下列程式碼取代 AddToCart.aspx.cs 程式碼後置中的現有程式碼:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Diagnostics;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
      public partial class AddToCart : System.Web.UI.Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
          string rawId = Request.QueryString["ProductID"];
          int productId;
          if (!String.IsNullOrEmpty(rawId) && int.TryParse(rawId, out productId))
          {
            using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
            {
              usersShoppingCart.AddToCart(Convert.ToInt16(rawId));
            }
    
          }
          else
          {
            Debug.Fail("ERROR : We should never get to AddToCart.aspx without a ProductId.");
            throw new Exception("ERROR : It is illegal to load AddToCart.aspx without setting a ProductId.");
          }
          Response.Redirect("ShoppingCart.aspx");
        }
      }
    }
    

載入 AddToCart.aspx 頁面時,會從查詢字串擷取產品 ID 。 接下來,會建立購物車類別的實例,並用來呼叫 AddToCart 您稍早在本教學課程中新增的方法。 AddToCart包含在 ShoppingCartActions.cs檔案中的 方法包含將選取的產品新增至購物車或遞增所選產品的產品數量邏輯。 如果產品尚未新增至購物車,則會將產品新增至 CartItem 資料庫的資料表。 如果產品已新增至購物車,且使用者新增相同產品的額外專案,產品數量就會在資料表中 CartItem 遞增。 最後,頁面會重新導向回您將在下一個步驟中新增的 ShoppingCart.aspx 頁面,使用者在購物車中看到更新的專案清單。

如先前所述,使用者 ID 會用來識別與特定使用者相關聯的產品。 每當使用者將產品新增至購物車時,這會 ID 新增至資料表中的資料 CartItem 列。

建立購物車 UI

[ShoppingCart.aspx] 頁面會顯示使用者已新增至購物車的產品。 它也可讓您新增、移除和更新購物車中的專案。

  1. 方案總管中,以滑鼠右鍵按一下WingtipToys,然後按一下 [新增- >新增專案]。
    [ 加入新項目 ] 對話方塊隨即出現。

  2. 使用主版頁面選取 [Web 表單],以新增網頁 (Web Form) 包含 主版頁面。 將新頁面命名為 ShoppingCart.aspx

  3. 選取 [Site.Master ],將主版頁面附加至新建立 的 .aspx 頁面。

  4. [ShoppingCart.aspx ] 頁面中,以下列標記取代現有的標記:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="ShoppingCart.aspx.cs" Inherits="WingtipToys.ShoppingCart" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <div id="ShoppingCartTitle" runat="server" class="ContentHead"><h1>Shopping Cart</h1></div>
        <asp:GridView ID="CartList" runat="server" AutoGenerateColumns="False" ShowFooter="True" GridLines="Vertical" CellPadding="4"
            ItemType="WingtipToys.Models.CartItem" SelectMethod="GetShoppingCartItems" 
            CssClass="table table-striped table-bordered" >   
            <Columns>
            <asp:BoundField DataField="ProductID" HeaderText="ID" SortExpression="ProductID" />        
            <asp:BoundField DataField="Product.ProductName" HeaderText="Name" />        
            <asp:BoundField DataField="Product.UnitPrice" HeaderText="Price (each)" DataFormatString="{0:c}"/>     
            <asp:TemplateField   HeaderText="Quantity">            
                    <ItemTemplate>
                        <asp:TextBox ID="PurchaseQuantity" Width="40" runat="server" Text="<%#: Item.Quantity %>"></asp:TextBox> 
                    </ItemTemplate>        
            </asp:TemplateField>    
            <asp:TemplateField HeaderText="Item Total">            
                    <ItemTemplate>
                        <%#: String.Format("{0:c}", ((Convert.ToDouble(Item.Quantity)) *  Convert.ToDouble(Item.Product.UnitPrice)))%>
                    </ItemTemplate>        
            </asp:TemplateField> 
            <asp:TemplateField HeaderText="Remove Item">            
                    <ItemTemplate>
                        <asp:CheckBox id="Remove" runat="server"></asp:CheckBox>
                    </ItemTemplate>        
            </asp:TemplateField>    
            </Columns>    
        </asp:GridView>
        <div>
            <p></p>
            <strong>
                <asp:Label ID="LabelTotalText" runat="server" Text="Order Total: "></asp:Label>
                <asp:Label ID="lblTotal" runat="server" EnableViewState="false"></asp:Label>
            </strong> 
        </div>
        <br />
    </asp:Content>
    

ShoppingCart.aspx頁面包含名為 的 CartListGridView控制項。 此控制項會使用模型系結,將購物車資料從資料庫系結至 GridView 控制項。 當您設定 ItemTypeGridView 控制項的 屬性時,資料系結運算式 Item 可在控制項的標記中使用,而且控制項會變成強型別。 如本教學課程系列稍早所述,您可以使用 IntelliSense 選取物件的詳細 Item 資料。 若要設定資料控制項以使用模型系結來選取資料,您可以設定 SelectMethod 控制項的 屬性。 在上述標記中,您會將 設定 SelectMethod 為使用 GetShoppingCartItems 方法,此方法會傳回物件清單 CartItemGridView資料控制項會在頁面生命週期中適當時間呼叫 方法,並自動系結傳回的資料。 GetShoppingCartItems方法仍必須加入。

擷取購物車專案

接下來,您會將程式碼新增至 ShoppingCart.aspx.cs 程式碼後置,以擷取並填入購物車 UI。

  1. 方案總管中,以滑鼠右鍵按一下[ShoppingCart.aspx] 頁面,然後按一下 [檢視程式碼]。 在編輯器中開啟 ShoppingCart.aspx.cs 程式碼後置檔案。

  2. 將現有的程式碼取代為下列程式碼:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
      public partial class ShoppingCart : System.Web.UI.Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    
        public List<CartItem> GetShoppingCartItems()
        {
          ShoppingCartActions actions = new ShoppingCartActions();
          return actions.GetCartItems();
        }
      }
    }
    

如上所述, GridView 資料控制項會在頁面生命週期中的適當時間呼叫 GetShoppingCartItems 方法,並自動系結傳回的資料。 方法 GetShoppingCartItems 會建立 物件的 ShoppingCartActions 實例。 然後,程式碼會使用該實例來傳回購物車中的專案,方法是呼叫 GetCartItems 方法。

將產品新增至購物車

當顯示 ProductList.aspxProductDetails.aspx 頁面時,使用者將能夠使用連結將產品新增至購物車。 當他們按一下連結時,應用程式會流覽至名為 AddToCart.aspx的處理頁面。 AddToCart.aspx頁面會在您稍早在本教學課程中新增的 ShoppingCart 類別中呼叫 AddToCart 方法。

現在,您會將 [ 新增至購物車 ] 連結新增至 ProductList.aspx 頁面和 ProductDetails.aspx 頁面。 此連結將包含從資料庫擷取的產品 ID

  1. 方案總管中,尋找並開啟名為ProductList.aspx的頁面。

  2. 將醒目提示的標記新增至 ProductList.aspx 頁面,讓整個頁面如下所示:

    <%@ Page Title="Products" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" 
             CodeBehind="ProductList.aspx.cs" Inherits="WingtipToys.ProductList" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <section>
            <div>
                <hgroup>
                    <h2><%: Page.Title %></h2>
                </hgroup>
    
                <asp:ListView ID="productList" runat="server" 
                    DataKeyNames="ProductID" GroupItemCount="4"
                    ItemType="WingtipToys.Models.Product" SelectMethod="GetProducts">
                    <EmptyDataTemplate>
                        <table runat="server">
                            <tr>
                                <td>No data was returned.</td>
                            </tr>
                        </table>
                    </EmptyDataTemplate>
                    <EmptyItemTemplate>
                        <td runat="server" />
                    </EmptyItemTemplate>
                    <GroupTemplate>
                        <tr id="itemPlaceholderContainer" runat="server">
                            <td id="itemPlaceholder" runat="server"></td>
                        </tr>
                    </GroupTemplate>
                    <ItemTemplate>
                        <td runat="server">
                            <table>
                                <tr>
                                    <td>
                                        <a href="ProductDetails.aspx?productID=<%#:Item.ProductID%>">
                                            <img src="/Catalog/Images/Thumbs/<%#:Item.ImagePath%>"
                                                width="100" height="75" style="border: solid" /></a>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        <a href="ProductDetails.aspx?productID=<%#:Item.ProductID%>">
                                            <span>
                                                <%#:Item.ProductName%>
                                            </span>
                                        </a>
                                        <br />
                                        <span>
                                            <b>Price: </b><%#:String.Format("{0:c}", Item.UnitPrice)%>
                                        </span>
                                        <br />
                                        <a href="/AddToCart.aspx?productID=<%#:Item.ProductID %>">               
                                            <span class="ProductListItem">
                                                <b>Add To Cart<b>
                                            </span>           
                                        </a>
                                    </td>
                                </tr>
                                <tr>
                                    <td>&nbsp;</td>
                                </tr>
                            </table>
                            </p>
                        </td>
                    </ItemTemplate>
                    <LayoutTemplate>
                        <table runat="server" style="width:100%;">
                            <tbody>
                                <tr runat="server">
                                    <td runat="server">
                                        <table id="groupPlaceholderContainer" runat="server" style="width:100%">
                                            <tr id="groupPlaceholder" runat="server"></tr>
                                        </table>
                                    </td>
                                </tr>
                                <tr runat="server">
                                    <td runat="server"></td>
                                </tr>
                                <tr></tr>
                            </tbody>
                        </table>
                    </LayoutTemplate>
                </asp:ListView>
            </div>
        </section>
    </asp:Content>
    

測試購物車

執行應用程式以查看如何將產品新增至購物車。

  1. F5 鍵執行應用程式。
    在專案重新建立資料庫之後,瀏覽器會開啟並顯示 Default.aspx 頁面。

  2. 從類別導覽功能表中選取 [汽車 ]。
    [ProductList.aspx] 頁面隨即顯示,只顯示 「Cars」 類別中包含的產品。

    購物車 - 汽車

  3. 按一下可轉換汽車) (所列第一個產品的 [ 新增至購物車 ] 連結。
    [ShoppingCart.aspx] 頁面隨即顯示,其中顯示購物車中的選取專案。

    購物車 - 購物車

  4. 從類別導覽功能表中選取 [平面 ],以檢視其他產品。

  5. 按一下列出的第一個產品旁的 [ 新增至購物車 ] 連結。
    ShoppingCart.aspx頁面會顯示其他專案。

  6. 關閉瀏覽器。

計算和顯示訂單總計

除了將產品新增至購物車之外,您還可以將方法新增 GetTotalShoppingCart 類別,並在購物車頁面中顯示訂單金額總計。

  1. 方案總管中,開啟Logic資料夾中的ShoppingCartActions.cs檔案。

  2. 將以黃色醒目提示的下列 GetTotal 方法新增至 ShoppingCart 類別,讓 類別如下所示:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    
    namespace WingtipToys.Logic
    {
      public class ShoppingCartActions : IDisposable
      {
        public string ShoppingCartId { get; set; }
    
        private ProductContext _db = new ProductContext();
    
        public const string CartSessionKey = "CartId";
    
        public void AddToCart(int id)
        {
          // Retrieve the product from the database.           
          ShoppingCartId = GetCartId();
    
          var cartItem = _db.ShoppingCartItems.SingleOrDefault(
              c => c.CartId == ShoppingCartId
              && c.ProductId == id);
          if (cartItem == null)
          {
            // Create a new cart item if no cart item exists.                 
            cartItem = new CartItem
            {
              ItemId = Guid.NewGuid().ToString(),
              ProductId = id,
              CartId = ShoppingCartId,
              Product = _db.Products.SingleOrDefault(
               p => p.ProductID == id),
              Quantity = 1,
              DateCreated = DateTime.Now
            };
    
            _db.ShoppingCartItems.Add(cartItem);
          }
          else
          {
            // If the item does exist in the cart,                  
            // then add one to the quantity.                 
            cartItem.Quantity++;
          }
          _db.SaveChanges();
        }
    
        public void Dispose()
        {
          if (_db != null)
          {
            _db.Dispose();
            _db = null;
          }
        }
    
        public string GetCartId()
        {
          if (HttpContext.Current.Session[CartSessionKey] == null)
          {
            if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
            {
              HttpContext.Current.Session[CartSessionKey] = HttpContext.Current.User.Identity.Name;
            }
            else
            {
              // Generate a new random GUID using System.Guid class.     
              Guid tempCartId = Guid.NewGuid();
              HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString();
            }
          }
          return HttpContext.Current.Session[CartSessionKey].ToString();
        }
    
        public List<CartItem> GetCartItems()
        {
          ShoppingCartId = GetCartId();
    
          return _db.ShoppingCartItems.Where(
              c => c.CartId == ShoppingCartId).ToList();
        }
    
        public decimal GetTotal()
        {
          ShoppingCartId = GetCartId();
          // Multiply product price by quantity of that product to get        
          // the current price for each of those products in the cart.  
          // Sum all product price totals to get the cart total.   
          decimal? total = decimal.Zero;
          total = (decimal?)(from cartItems in _db.ShoppingCartItems
                             where cartItems.CartId == ShoppingCartId
                             select (int?)cartItems.Quantity *
                             cartItems.Product.UnitPrice).Sum();
          return total ?? decimal.Zero;
        }
      }
    }
    

首先, GetTotal 方法會取得使用者的購物車識別碼。 然後,方法會藉由將產品價格乘以購物車中所列每個產品的產品數量來取得購物車總計。

注意

上述程式碼會使用可為 Null 的類型 「 int? 」。 可為 Null 的型別可以代表基礎類型的所有值,也可以表示為 Null 值。 如需詳細資訊,請參閱 使用可為 Null 的型別

修改購物車顯示

接下來,您將修改 ShoppingCart.aspx 頁面的程式碼來呼叫 GetTotal 方法,並在載入頁面時,在 ShoppingCart.aspx 頁面上顯示該總計。

  1. 方案總管中,以滑鼠右鍵按一下[ShoppingCart.aspx] 頁面,然後選取 [檢視程式碼]。

  2. ShoppingCart.aspx.cs 檔案中,新增以黃色醒目提示的下列程式碼來更新 Page_Load 處理常式:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
      public partial class ShoppingCart : System.Web.UI.Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
          using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
          {
            decimal cartTotal = 0;
            cartTotal = usersShoppingCart.GetTotal();
            if (cartTotal > 0)
            {
              // Display Total.
              lblTotal.Text = String.Format("{0:c}", cartTotal);
            }
            else
            {
              LabelTotalText.Text = "";
              lblTotal.Text = "";
              ShoppingCartTitle.InnerText = "Shopping Cart is Empty";
            }
          }
        }
    
        public List<CartItem> GetShoppingCartItems()
        {
          ShoppingCartActions actions = new ShoppingCartActions();
          return actions.GetCartItems();
        }
      }
    }
    

當 ShoppingCart.aspx頁面載入時,它會載入購物車物件,然後藉由呼叫 GetTotal 類別的 ShoppingCart 方法擷取購物車總計。 如果購物車是空的,就會顯示該效果的訊息。

測試購物車總計

立即執行應用程式,以瞭解您不只可將產品新增至購物車,還可以查看購物車總計。

  1. F5 鍵執行應用程式。
    瀏覽器便會開啟並顯示 Default.aspx 頁面。

  2. 從類別導覽功能表中選取 [汽車 ]。

  3. 按一下第一個產品旁的 [ 新增至購物車 ] 連結。
    ShoppingCart.aspx頁面會顯示訂單總計。

    購物車 - 購物車總計

  4. 例如,將一些其他產品新增至購物車 (平面) 。

  5. [ShoppingCart.aspx] 頁面會顯示您所新增之所有產品的更新總計。

    購物車 - 多個產品

  6. 關閉瀏覽器視窗以停止執行中的應用程式。

將 [更新] 和 [結帳] 按鈕新增至購物車

若要允許使用者修改購物車,您會將 [ 更新] 按鈕和 [結帳 ] 按鈕新增至購物車頁面。 在本教學課程系列稍後之前,不會使用 [簽出 ] 按鈕。

  1. 方案總管中,開啟 Web 應用程式專案根目錄中的ShoppingCart.aspx頁面。

  2. 若要將 [更新] 按鈕和 [結帳 ] 按鈕新增至 ShoppingCart.aspx 頁面,請將以黃色醒目提示的標記新增至現有的標記,如下列程式碼所示:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="ShoppingCart.aspx.cs" Inherits="WingtipToys.ShoppingCart" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <div id="ShoppingCartTitle" runat="server" class="ContentHead"><h1>Shopping Cart</h1></div>
        <asp:GridView ID="CartList" runat="server" AutoGenerateColumns="False" ShowFooter="True" GridLines="Vertical" CellPadding="4"
            ItemType="WingtipToys.Models.CartItem" SelectMethod="GetShoppingCartItems"  
            CssClass="table table-striped table-bordered" >   
            <Columns>
            <asp:BoundField DataField="ProductID" HeaderText="ID" SortExpression="ProductID" />        
            <asp:BoundField DataField="Product.ProductName" HeaderText="Name" />        
            <asp:BoundField DataField="Product.UnitPrice" HeaderText="Price (each)" DataFormatString="{0:c}"/>     
            <asp:TemplateField   HeaderText="Quantity">            
                    <ItemTemplate>
                        <asp:TextBox ID="PurchaseQuantity" Width="40" runat="server" Text="<%#: Item.Quantity %>"></asp:TextBox> 
                    </ItemTemplate>        
            </asp:TemplateField>    
            <asp:TemplateField HeaderText="Item Total">            
                    <ItemTemplate>
                        <%#: String.Format("{0:c}", ((Convert.ToDouble(Item.Quantity)) *  Convert.ToDouble(Item.Product.UnitPrice)))%>
                    </ItemTemplate>        
            </asp:TemplateField> 
            <asp:TemplateField HeaderText="Remove Item">            
                    <ItemTemplate>
                        <asp:CheckBox id="Remove" runat="server"></asp:CheckBox>
                    </ItemTemplate>        
            </asp:TemplateField>    
            </Columns>    
        </asp:GridView>
        <div>
            <p></p>
            <strong>
                <asp:Label ID="LabelTotalText" runat="server" Text="Order Total: "></asp:Label>
                <asp:Label ID="lblTotal" runat="server" EnableViewState="false"></asp:Label>
            </strong> 
        </div>
      <br />
        <table> 
        <tr>
          <td>
            <asp:Button ID="UpdateBtn" runat="server" Text="Update" OnClick="UpdateBtn_Click" />
          </td>
          <td>
            <!--Checkout Placeholder -->
          </td>
        </tr>
        </table>
    </asp:Content>
    

當使用者按一下 [ 更新] 按鈕時, UpdateBtn_Click 將會呼叫事件處理常式。 此事件處理常式會呼叫您將在下一個步驟中新增的程式碼。

接下來,您可以更新 ShoppingCart.aspx.cs 檔案中包含的程式碼,以迴圈查看購物車專案,並呼叫 RemoveItemUpdateItem 方法。

  1. 方案總管中,開啟 Web 應用程式專案根目錄中的ShoppingCart.aspx.cs檔案。

  2. 將下列以黃色醒目提示的程式碼區段新增至 ShoppingCart.aspx.cs 檔案:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    using System.Collections.Specialized;
    using System.Collections;
    using System.Web.ModelBinding;
    
    namespace WingtipToys
    {
      public partial class ShoppingCart : System.Web.UI.Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
          using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
          {
            decimal cartTotal = 0;
            cartTotal = usersShoppingCart.GetTotal();
            if (cartTotal > 0)
            {
              // Display Total.
              lblTotal.Text = String.Format("{0:c}", cartTotal);
            }
            else
            {
              LabelTotalText.Text = "";
              lblTotal.Text = "";
              ShoppingCartTitle.InnerText = "Shopping Cart is Empty";
              UpdateBtn.Visible = false;
            }
          }
        }
    
        public List<CartItem> GetShoppingCartItems()
        {
          ShoppingCartActions actions = new ShoppingCartActions();
          return actions.GetCartItems();
        }
    
        public List<CartItem> UpdateCartItems()
        {
          using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
          {
            String cartId = usersShoppingCart.GetCartId();
    
            ShoppingCartActions.ShoppingCartUpdates[] cartUpdates = new ShoppingCartActions.ShoppingCartUpdates[CartList.Rows.Count];
            for (int i = 0; i < CartList.Rows.Count; i++)
            {
              IOrderedDictionary rowValues = new OrderedDictionary();
              rowValues = GetValues(CartList.Rows[i]);
              cartUpdates[i].ProductId = Convert.ToInt32(rowValues["ProductID"]);
    
              CheckBox cbRemove = new CheckBox();
              cbRemove = (CheckBox)CartList.Rows[i].FindControl("Remove");
              cartUpdates[i].RemoveItem = cbRemove.Checked;
    
              TextBox quantityTextBox = new TextBox();
              quantityTextBox = (TextBox)CartList.Rows[i].FindControl("PurchaseQuantity");
              cartUpdates[i].PurchaseQuantity = Convert.ToInt16(quantityTextBox.Text.ToString());
            }
            usersShoppingCart.UpdateShoppingCartDatabase(cartId, cartUpdates);
            CartList.DataBind();
            lblTotal.Text = String.Format("{0:c}", usersShoppingCart.GetTotal());
            return usersShoppingCart.GetCartItems();
          }
        }
    
        public static IOrderedDictionary GetValues(GridViewRow row)
        {
          IOrderedDictionary values = new OrderedDictionary();
          foreach (DataControlFieldCell cell in row.Cells)
          {
            if (cell.Visible)
            {
              // Extract values from the cell.
              cell.ContainingField.ExtractValuesFromCell(values, cell, row.RowState, true);
            }
          }
          return values;
        }
    
        protected void UpdateBtn_Click(object sender, EventArgs e)
        {
          UpdateCartItems();
        }
      }
    }
    

當使用者按一下[ShoppingCart.aspx] 頁面上的 [更新] 按鈕時,會呼叫 UpdateCartItems 方法。 UpdateCartItems 方法會取得購物車中每個專案的更新值。 然後,UpdateCartItems 方法會呼叫 UpdateShoppingCartDatabase 方法 (新增,並在下一個步驟中說明,) 新增或移除購物車中的專案。 一旦資料庫更新以反映購物車的更新, GridView 控制項就會藉由呼叫 DataBindGridView的 方法來更新購物車頁面上。 此外,購物車頁面上的訂單金額總計也會更新,以反映更新的專案清單。

更新和移除購物車專案

[ShoppingCart.aspx ] 頁面上,您可以看到已新增控制項來更新專案的數量並移除專案。 現在,新增可讓這些控制項運作的程式碼。

  1. 方案總管中,開啟Logic資料夾中的ShoppingCartActions.cs檔案。

  2. 將下列以黃色醒目提示的程式碼新增至 ShoppingCartActions.cs 類別檔案:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    
    namespace WingtipToys.Logic
    {
      public class ShoppingCartActions : IDisposable
      {
        public string ShoppingCartId { get; set; }
    
        private ProductContext _db = new ProductContext();
    
        public const string CartSessionKey = "CartId";
    
        public void AddToCart(int id)
        {
          // Retrieve the product from the database.           
          ShoppingCartId = GetCartId();
    
          var cartItem = _db.ShoppingCartItems.SingleOrDefault(
              c => c.CartId == ShoppingCartId
              && c.ProductId == id);
          if (cartItem == null)
          {
            // Create a new cart item if no cart item exists.                 
            cartItem = new CartItem
            {
              ItemId = Guid.NewGuid().ToString(),
              ProductId = id,
              CartId = ShoppingCartId,
              Product = _db.Products.SingleOrDefault(
               p => p.ProductID == id),
              Quantity = 1,
              DateCreated = DateTime.Now
            };
    
            _db.ShoppingCartItems.Add(cartItem);
          }
          else
          {
            // If the item does exist in the cart,                  
            // then add one to the quantity.                 
            cartItem.Quantity++;
          }
          _db.SaveChanges();
        }
    
        public void Dispose()
        {
          if (_db != null)
          {
            _db.Dispose();
            _db = null;
          }
        }
    
        public string GetCartId()
        {
          if (HttpContext.Current.Session[CartSessionKey] == null)
          {
            if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
            {
              HttpContext.Current.Session[CartSessionKey] = HttpContext.Current.User.Identity.Name;
            }
            else
            {
              // Generate a new random GUID using System.Guid class.     
              Guid tempCartId = Guid.NewGuid();
              HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString();
            }
          }
          return HttpContext.Current.Session[CartSessionKey].ToString();
        }
    
        public List<CartItem> GetCartItems()
        {
          ShoppingCartId = GetCartId();
    
          return _db.ShoppingCartItems.Where(
              c => c.CartId == ShoppingCartId).ToList();
        }
    
        public decimal GetTotal()
        {
          ShoppingCartId = GetCartId();
          // Multiply product price by quantity of that product to get        
          // the current price for each of those products in the cart.  
          // Sum all product price totals to get the cart total.   
          decimal? total = decimal.Zero;
          total = (decimal?)(from cartItems in _db.ShoppingCartItems
                             where cartItems.CartId == ShoppingCartId
                             select (int?)cartItems.Quantity *
                             cartItems.Product.UnitPrice).Sum();
          return total ?? decimal.Zero;
        }
    
        public ShoppingCartActions GetCart(HttpContext context)
        {
          using (var cart = new ShoppingCartActions())
          {
            cart.ShoppingCartId = cart.GetCartId();
            return cart;
          }
        }
    
        public void UpdateShoppingCartDatabase(String cartId, ShoppingCartUpdates[] CartItemUpdates)
        {
          using (var db = new WingtipToys.Models.ProductContext())
          {
            try
            {
              int CartItemCount = CartItemUpdates.Count();
              List<CartItem> myCart = GetCartItems();
              foreach (var cartItem in myCart)
              {
                // Iterate through all rows within shopping cart list
                for (int i = 0; i < CartItemCount; i++)
                {
                  if (cartItem.Product.ProductID == CartItemUpdates[i].ProductId)
                  {
                    if (CartItemUpdates[i].PurchaseQuantity < 1 || CartItemUpdates[i].RemoveItem == true)
                    {
                      RemoveItem(cartId, cartItem.ProductId);
                    }
                    else
                    {
                      UpdateItem(cartId, cartItem.ProductId, CartItemUpdates[i].PurchaseQuantity);
                    }
                  }
                }
              }
            }
            catch (Exception exp)
            {
              throw new Exception("ERROR: Unable to Update Cart Database - " + exp.Message.ToString(), exp);
            }
          }
        }
    
        public void RemoveItem(string removeCartID, int removeProductID)
        {
          using (var _db = new WingtipToys.Models.ProductContext())
          {
            try
            {
              var myItem = (from c in _db.ShoppingCartItems where c.CartId == removeCartID && c.Product.ProductID == removeProductID select c).FirstOrDefault();
              if (myItem != null)
              {
                // Remove Item.
                _db.ShoppingCartItems.Remove(myItem);
                _db.SaveChanges();
              }
            }
            catch (Exception exp)
            {
              throw new Exception("ERROR: Unable to Remove Cart Item - " + exp.Message.ToString(), exp);
            }
          }
        }
    
        public void UpdateItem(string updateCartID, int updateProductID, int quantity)
        {
          using (var _db = new WingtipToys.Models.ProductContext())
          {
            try
            {
              var myItem = (from c in _db.ShoppingCartItems where c.CartId == updateCartID && c.Product.ProductID == updateProductID select c).FirstOrDefault();
              if (myItem != null)
              {
                myItem.Quantity = quantity;
                _db.SaveChanges();
              }
            }
            catch (Exception exp)
            {
              throw new Exception("ERROR: Unable to Update Cart Item - " + exp.Message.ToString(), exp);
            }
          }
        }
    
        public void EmptyCart()
        {
          ShoppingCartId = GetCartId();
          var cartItems = _db.ShoppingCartItems.Where(
              c => c.CartId == ShoppingCartId);
          foreach (var cartItem in cartItems)
          {
            _db.ShoppingCartItems.Remove(cartItem);
          }
          // Save changes.             
          _db.SaveChanges();
        }
    
        public int GetCount()
        {
          ShoppingCartId = GetCartId();
    
          // Get the count of each item in the cart and sum them up          
          int? count = (from cartItems in _db.ShoppingCartItems
                        where cartItems.CartId == ShoppingCartId
                        select (int?)cartItems.Quantity).Sum();
          // Return 0 if all entries are null         
          return count ?? 0;
        }
    
        public struct ShoppingCartUpdates
        {
          public int ProductId;
          public int PurchaseQuantity;
          public bool RemoveItem;
        }
      }
    }
    

UpdateShoppingCartDatabaseUpdateCartItems[ShoppingCart.aspx.cs ] 頁面上的 方法呼叫的方法包含從購物車更新或移除專案的邏輯。 方法 UpdateShoppingCartDatabase 會逐一查看購物車清單內的所有資料列。 如果購物車專案已標示為要移除,或數量小於一,則會 RemoveItem 呼叫 方法。 否則,呼叫 方法時 UpdateItem ,會檢查購物車專案是否有更新。 移除或更新購物車專案之後,就會儲存資料庫變更。

結構 ShoppingCartUpdates 是用來保存所有購物車專案。 方法 UpdateShoppingCartDatabaseShoppingCartUpdates 使用 結構來判斷是否需要更新或移除任何專案。

在下一個教學課程中,您將使用 EmptyCart 方法來清除購買產品後的購物車。 但現在,您將使用 GetCount 剛新增至 ShoppingCartActions.cs 檔案的方法,來判斷購物車中的專案數目。

新增購物車計數器

若要允許使用者檢視購物車中的專案總數,您會將計數器新增至 Site.Master 頁面。 此計數器也會作為購物車的連結。

  1. 方案總管中,開啟[Site.Master] 頁面。

  2. 將購物車計數器連結新增至導覽區段,以修改標記,如下所示:

    <ul class="nav navbar-nav">
          <li><a runat="server" href="~/">Home</a></li>
          <li><a runat="server" href="~/About">About</a></li>
          <li><a runat="server" href="~/Contact">Contact</a></li>
          <li><a runat="server" href="~/ProductList">Products</a></li>
          <li><a runat="server" href="~/ShoppingCart" ID="cartCount">&nbsp;</a></li>
      </ul>
    
  3. 接下來,新增以黃色醒目提示的程式碼,以更新 Site.Master.cs 檔案的程式碼後置,如下所示:

    using System;
    using System.Collections.Generic;
    using System.Security.Claims;
    using System.Security.Principal;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Linq;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
        public partial class SiteMaster : MasterPage
        {
            private const string AntiXsrfTokenKey = "__AntiXsrfToken";
            private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
            private string _antiXsrfTokenValue;
    
            protected void Page_Init(object sender, EventArgs e)
            {
                // The code below helps to protect against XSRF attacks
                var requestCookie = Request.Cookies[AntiXsrfTokenKey];
                Guid requestCookieGuidValue;
                if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
                {
                    // Use the Anti-XSRF token from the cookie
                    _antiXsrfTokenValue = requestCookie.Value;
                    Page.ViewStateUserKey = _antiXsrfTokenValue;
                }
                else
                {
                    // Generate a new Anti-XSRF token and save to the cookie
                    _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
                    Page.ViewStateUserKey = _antiXsrfTokenValue;
    
                    var responseCookie = new HttpCookie(AntiXsrfTokenKey)
                    {
                        HttpOnly = true,
                        Value = _antiXsrfTokenValue
                    };
                    if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
                    {
                        responseCookie.Secure = true;
                    }
                    Response.Cookies.Set(responseCookie);
                }
    
                Page.PreLoad += master_Page_PreLoad;
            }
    
            protected void master_Page_PreLoad(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    // Set Anti-XSRF token
                    ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
                    ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
                }
                else
                {
                    // Validate the Anti-XSRF token
                    if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
                        || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
                    {
                        throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
                    }
                }
            }
    
            protected void Page_Load(object sender, EventArgs e)
            {
    
            }
    
            protected void Page_PreRender(object sender, EventArgs e)
            {
              using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
              {
                string cartStr = string.Format("Cart ({0})", usersShoppingCart.GetCount());
                cartCount.InnerText = cartStr;
              }
            }
    
            public IQueryable<Category> GetCategories()
            {
              var _db = new WingtipToys.Models.ProductContext();
              IQueryable<Category> query = _db.Categories;
              return query;
            }
    
            protected void Unnamed_LoggingOut(object sender, LoginCancelEventArgs e)
            {
                Context.GetOwinContext().Authentication.SignOut();
            }
        }
    }
    

在頁面轉譯為 HTML 之前,會 Page_PreRender 引發 事件。 在 Page_PreRender 處理常式中,購物車的總計數是藉由呼叫 GetCount 方法來決定。 傳回的值會新增至 cartCountSite.Master 頁面標記中包含的範圍。 卷 <span> 標可讓內部元素正確轉譯。 當網站的任何頁面顯示時,就會顯示購物車總計。 使用者也可以按一下購物車總計以顯示購物車。

測試已完成的購物車

您現在可以執行應用程式,以查看如何在購物車中新增、刪除和更新專案。 購物車總計將反映購物車中所有專案的總成本。

  1. F5 鍵執行應用程式。
    瀏覽器隨即開啟,並顯示 Default.aspx 頁面。

  2. 從類別導覽功能表中選取 [汽車 ]。

  3. 按一下第一個產品旁的 [ 新增至購物車 ] 連結。
    ShoppingCart.aspx頁面會顯示訂單總計。

  4. 從類別導覽功能表中選取 [平面 ]。

  5. 按一下第一個產品旁的 [ 新增至購物車 ] 連結。

  6. 將購物車中第一個專案的數量設定為 3,然後選取第二個專案的 [ 移除專案 ] 核取方塊。

  7. 按一下 [ 更新] 按鈕以更新購物車頁面,並顯示新的訂單總計。

    購物車 - 購物車更新

總結

在本教學課程中,您已為 Wingtip Toys Web Form範例應用程式建立購物車。 在本教學課程中,您已使用 Entity Framework Code First、資料批註、強型別資料控制項和模型系結。

購物車支援新增、刪除和更新使用者已選取購買的專案。 除了實作購物車功能之外,您已瞭解如何在 GridView 控制項中顯示購物車專案,並計算訂單總計。

若要瞭解描述的功能在實際商務應用程式中的運作方式,您可以檢視nop Business - ASP.NET 型開放原始碼電子商務購物車的範例。 最初,它是建置在Web Form上,而且在幾年內移至 MVC,現在移至 ASP.NET Core。

加法資訊

ASP.NET 工作階段狀態概觀