Nákupní košík
Stáhnout ukázkový projekt Wingtip Toys (C#) nebo Stáhnout elektronickou knihu (PDF)
Tato série kurzů vás naučí základy vytváření ASP.NET Web Forms aplikace pomocí ASP.NET 4.5 a Microsoft Visual Studio Express 2013 pro web. K dispozici je Visual Studio 2013 projekt se zdrojovým kódem jazyka C#, který bude doprovázet tuto sérii kurzů.
Tento kurz popisuje obchodní logiku potřebnou k přidání nákupního košíku do ukázkové aplikace Wingtip Toys ASP.NET Web Forms. Tento kurz vychází z předchozího kurzu "Zobrazení datových položek a podrobností" a je součástí série kurzů Wingtip Toy Store. Po dokončení tohoto kurzu budou moct uživatelé ukázkové aplikace přidávat, odebírat a upravovat produkty ve svém nákupním košíku.
Naučíte se:
- Postup vytvoření nákupního košíku pro webovou aplikaci
- Jak uživatelům povolit přidávání položek do nákupního košíku.
- Jak přidat ovládací prvek GridView pro zobrazení podrobností o nákupním košíku.
- Jak vypočítat a zobrazit celkový počet objednávek.
- Jak odebrat a aktualizovat položky v nákupním košíku.
- Jak zahrnout čítač nákupního košíku.
Funkce kódu v tomto kurzu:
- Entity Framework Code First
- Datové poznámky
- Ovládací prvky dat silného typu
- Vazby modelu
Vytvoření nákupního košíku
Dříve v této sérii kurzů jste přidali stránky a kód pro zobrazení dat o produktech z databáze. V tomto kurzu vytvoříte nákupní košík pro správu produktů, které mají uživatelé zájem koupit. Uživatelé budou moct procházet a přidávat položky do nákupního košíku, i když nejsou zaregistrovaní nebo přihlášení. Pokud chcete spravovat přístup k nákupnímu košíku, přiřadíte uživatelům jedinečný ID
identifikátor s použitím globálně jedinečného identifikátoru (GUID), když uživatel poprvé přistupuje k nákupnímu košíku. Uložíte ID
ho pomocí stavu relace ASP.NET.
Poznámka
Stav ASP.NET relace je vhodným místem pro ukládání informací specifických pro uživatele, jehož platnost vyprší, jakmile uživatel opustí web. I když zneužití stavu relace může mít vliv na výkon na větší weby, pro demonstrační účely funguje i lehké použití stavu relace. Ukázkový projekt Wingtip Toys ukazuje, jak používat stav relace bez externího poskytovatele, kde je stav relace uložen v procesu na webovém serveru, který je hostitelem webu. U větších lokalit, které poskytují více instancí aplikace, nebo pro lokality, na kterých běží více instancí aplikace na různých serverech, zvažte použití Služby mezipaměti Windows Azure. Tato služba mezipaměti poskytuje distribuovanou službu ukládání do mezipaměti, která je pro web externí, a řeší problém s používáním stavu relace v procesu. Další informace najdete v tématu Použití ASP.NET stavu relace s weby Windows Azure.
Přidání CartItem jako třídy modelu
Dříve v této sérii kurzů jste definovali schéma pro data kategorií a produktů vytvořením Category
tříd a ve Product
složce Modely . Teď přidejte novou třídu, která definuje schéma nákupního košíku. Později v tomto kurzu přidáte třídu, která bude zpracovávat přístup k datům tabulky CartItem
. Tato třída poskytne obchodní logiku pro přidání, odebrání a aktualizaci položek v nákupním košíku.
Klikněte pravým tlačítkem na složku Models (Modely) a vyberte Add -New Item (Přidat novou>položku).
Zobrazí se dialogové okno Přidat novou položku. Vyberte Kód a pak vyberte Třída.
Pojmenujte tuto novou třídu CartItem.cs.
Klikněte na Přidat.
Nový soubor třídy se zobrazí v editoru.Nahraďte výchozí kód následujícím kódem:
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; } } }
Třída CartItem
obsahuje schéma, které definuje každý produkt, který uživatel přidá do nákupního košíku. Tato třída je podobná ostatním třídám schématu, které jste vytvořili dříve v této sérii kurzů. Podle konvence Entity Framework Code First očekává, že primární klíč pro CartItem
tabulku bude buď CartItemId
nebo ID
. Kód však přepíše výchozí chování pomocí atributu datové poznámky [Key]
. Atribut Key
ItemId vlastnosti určuje, že ItemID
vlastnost je primární klíč.
Vlastnost CartId
určuje ID
uživatele, který je přidružen k položce, která se má koupit. Když uživatel přejde do nákupního košíku, přidáte kód pro vytvoření tohoto uživatele ID
. Tato ID
proměnná se také uloží jako proměnná relace ASP.NET.
Aktualizace kontextu produktu
Kromě přidání CartItem
třídy budete muset aktualizovat třídu kontextu databáze, která spravuje třídy entit a která poskytuje přístup k datům k databázi. Uděláte to tak, že do třídy přidáte nově vytvořenou CartItem
ProductContext
třídu modelu.
V Průzkumník řešení vyhledejte a otevřete soubor ProductContext.cs ve složce Modely.
Takto přidejte zvýrazněný kód do souboru 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; } } }
Jak bylo zmíněno dříve v této sérii kurzů, kód v souboru ProductContext.cs přidá System.Data.Entity
obor názvů, abyste měli přístup ke všem základním funkcím Entity Framework. Tato funkce zahrnuje možnost dotazování, vkládání, aktualizace a odstraňování dat pomocí práce s objekty silného typu. Třída ProductContext
přidá přístup k nově přidané CartItem
třídě modelu.
Správa obchodní logiky nákupního košíku
Dále vytvoříte ShoppingCart
třídu v nové složce Logika . Třída ShoppingCart
zpracovává přístup k datům k tabulce CartItem
. Třída bude také obsahovat obchodní logiku pro přidání, odebrání a aktualizaci položek v nákupním košíku.
Logika nákupního košíku, kterou přidáte, bude obsahovat funkce pro správu následujících akcí:
- Přidání položek do nákupního košíku
- Odebrání položek z nákupního košíku
- Získání ID nákupního košíku
- Načítání položek z nákupního košíku
- Součet všech položek nákupního košíku
- Aktualizace dat nákupního košíku
Stránka nákupního košíku (ShoppingCart.aspx) a třída nákupního košíku se použijí společně pro přístup k datům nákupního košíku. Na stránce nákupního košíku se zobrazí všechny položky, které uživatel přidá do nákupního košíku. Kromě stránky a třídy nákupního košíku vytvoříte stránku (AddToCart.aspx) pro přidání produktů do nákupního košíku. Na stránku ProductList.aspx a ProductDetails.aspx přidáte také kód, který poskytne odkaz na stránku AddToCart.aspx , aby uživatel mohl přidávat produkty do nákupního košíku.
Následující diagram znázorňuje základní proces, ke kterému dochází, když uživatel přidá produkt do nákupního košíku.
Když uživatel klikne na odkaz Přidat do košíku na stránce ProductList.aspx nebo Na stránce ProductDetails.aspx , aplikace přejde na stránku AddToCart.aspx a pak automaticky na stránku ShoppingCart.aspx . Stránka AddToCart.aspx přidá vybraný produkt do nákupního košíku voláním metody ve třídě ShoppingCart. Na stránce ShoppingCart.aspx se zobrazí produkty, které byly přidány do nákupního košíku.
Vytvoření třídy nákupního košíku
Třída ShoppingCart
se přidá do samostatné složky v aplikaci, aby bylo jasné rozlišení mezi modelem (složka Models), stránkami (kořenová složka) a logikou (složka Logika).
V Průzkumník řešení klikněte pravým tlačítkem na projekt WingtipToysa vyberte Přidat novou>složku. Pojmenujte novou složku Logika.
Klikněte pravým tlačítkem na složku Logika a pak vyberte Přidat ->Nová položka.
Přidejte nový soubor třídy s názvem ShoppingCartActions.cs.
Nahraďte výchozí kód následujícím kódem:
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(); } } }
Metoda AddToCart
umožňuje zahrnout jednotlivé produkty do nákupního košíku na základě produktu ID
. Produkt se přidá do košíku nebo pokud již košík obsahuje položku pro tento produkt, množství se zvýší.
Metoda GetCartId
vrátí košík ID
pro uživatele. Košík ID
slouží ke sledování položek, které má uživatel v nákupním košíku. Pokud uživatel nemá existující košík ID
, vytvoří se pro ně nový košík ID
. Pokud je uživatel přihlášený jako registrovaný uživatel, košík ID
se nastaví na jeho uživatelské jméno. Pokud však uživatel není přihlášený, je košík ID
nastaven na jedinečnou hodnotu (IDENTIFIKÁTOR GUID). Identifikátor GUID zajišťuje, že se pro každého uživatele vytvoří pouze jeden košík na základě relace.
Metoda GetCartItems
vrátí seznam položek nákupního košíku pro uživatele. Později v tomto kurzu uvidíte, že se vazba modelu používá k zobrazení položek košíku v nákupním košíku pomocí GetCartItems
metody .
Vytvoření funkce doplňku do košíku
Jak bylo zmíněno dříve, vytvoříte stránku zpracování s názvem AddToCart.aspx , která se použije k přidání nových produktů do nákupního košíku uživatele. Tato stránka bude volat metodu AddToCart
ShoppingCart
ve třídě, kterou jste právě vytvořili. Stránka AddToCart.aspx bude očekávat, že se do ní předá produkt ID
. Tento produkt ID
se použije při volání AddToCart
metody ve ShoppingCart
třídě.
Poznámka
Budete upravovat kód na pozadí (AddToCart.aspx.cs) pro tuto stránku, nikoli uživatelské rozhraní stránky (AddToCart.aspx).
Vytvoření funkce Přidat do košíku:
V Průzkumník řešení klikněte pravým tlačítkem na projekt WingtipToysa klikněte na Přidat ->Nová položka.
Zobrazí se dialogové okno Přidat novou položku.Přidejte do aplikace standardní novou stránku (webový formulář) s názvem AddToCart.aspx.
V Průzkumník řešení klikněte pravým tlačítkem na stránku AddToCart.aspx a potom klikněte na Zobrazit kód. Soubor kódu AddToCart.aspx.cs je otevřen v editoru.
Nahraďte existující kód v kódu AddToCart.aspx.cs následujícím kódem:
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"); } } }
Při načtení stránky AddToCart.aspx se produkt ID
načte z řetězce dotazu. Dále se vytvoří instance třídy nákupního košíku a použije se k volání AddToCart
metody, kterou jste přidali dříve v tomto kurzu. Metoda obsažená AddToCart
v souboru ShoppingCartActions.cs obsahuje logiku pro přidání vybraného produktu do nákupního košíku nebo zvýšení množství vybraného produktu. Pokud produkt nebyl přidán do nákupního košíku, přidá se do CartItem
tabulky databáze. Pokud už byl produkt přidán do nákupního košíku a uživatel přidá další položku stejného produktu, zvýší se v CartItem
tabulce množství produktu. Nakonec se stránka přesměruje zpět na stránku ShoppingCart.aspx , kterou přidáte v dalším kroku, kde uživatel uvidí aktualizovaný seznam položek v košíku.
Jak už jsme zmínili, uživatel ID
se používá k identifikaci produktů přidružených ke konkrétnímu uživateli. To ID
se přidá do řádku v CartItem
tabulce pokaždé, když uživatel přidá produkt do nákupního košíku.
Vytvoření uživatelského rozhraní nákupního košíku
Na stránce ShoppingCart.aspx se zobrazí produkty, které si uživatel přidal do svého nákupního košíku. Bude také poskytovat možnost přidávat, odebírat a aktualizovat položky v nákupním košíku.
V Průzkumník řešení klikněte pravým tlačítkem myši na WingtipToys a klikněte na Přidat ->Nová položka.
Zobrazí se dialogové okno Přidat novou položku.Výběrem možnosti Webový formulář pomocí stránky předlohy přidejte novou stránku (webový formulář), která obsahuje stránku předlohy. Pojmenujte novou stránku ShoppingCart.aspx.
Vyberte Site.Master a připojte stránku předlohy k nově vytvořené stránce .aspx .
Na stránce ShoppingCart.aspx nahraďte existující značku následujícím kódem:
<%@ 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>
Stránka ShoppingCart.aspx obsahuje ovládací prvek GridView s názvem CartList
. Tento ovládací prvek používá vazbu modelu k vytvoření vazby dat nákupního košíku z databáze s ovládacím prvku GridView . Když nastavíte ItemType
vlastnost ovládacího prvku GridView , je výraz Item
datové vazby k dispozici ve značkách ovládacího prvku a ovládací prvek se stane silným typem. Jak je uvedeno dříve v této sérii kurzů, můžete vybrat podrobnosti o objektu Item
pomocí IntelliSense. Pokud chcete nakonfigurovat ovládací prvek dat tak, aby k výběru dat používal vazbu modelu, nastavte SelectMethod
vlastnost ovládacího prvku. Ve výše uvedeném kódu nastavíte SelectMethod
na použití GetShoppingCartItems metoda, která vrátí seznam CartItem
objektů. Ovládací prvek dat GridView volá metodu v příslušném čase v životním cyklu stránky a automaticky sváže vrácená data. Metoda GetShoppingCartItems
musí být stále přidána.
Načítání položek nákupního košíku
Dále přidáte kód do kódu ShoppingCart.aspx.cs , který načte a naplní uživatelské rozhraní nákupního košíku.
V Průzkumník řešení klikněte pravým tlačítkem na stránku ShoppingCart.aspx a pak klikněte na Zobrazit kód. Soubor kódu na pozadí ShoppingCart.aspx.cs se otevře v editoru.
Nahraďte existující kód následujícím kódem:
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(); } } }
Jak je uvedeno výše, GridView
ovládací prvek dat volá metodu GetShoppingCartItems
ve vhodný čas v životním cyklu stránky a automaticky sváže vrácená data. Metoda GetShoppingCartItems
vytvoří instanci objektu ShoppingCartActions
. Pak kód použije danou instanci k vrácení položek v košíku voláním GetCartItems
metody.
Přidání produktů do nákupního košíku
Když se zobrazí stránka ProductList.aspx nebo ProductDetails.aspx , uživatel bude moct přidat produkt do nákupního košíku pomocí odkazu. Když na odkaz kliknou, aplikace přejde na stránku zpracování s názvem AddToCart.aspx. Stránka AddToCart.aspx bude volat metodu AddToCart
ShoppingCart
ve třídě, kterou jste přidali dříve v tomto kurzu.
Teď přidáte odkaz Přidat do košíku na stránku ProductList.aspx i na stránku ProductDetails.aspx . Tento odkaz bude obsahovat produkt ID
, který je načten z databáze.
V Průzkumník řešení vyhledejte a otevřete stránku s názvem ProductList.aspx.
Přidejte žlutě zvýrazněné značky na stránku ProductList.aspx tak, aby celá stránka byla takto:
<%@ 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> </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>
Testování nákupního košíku
Spusťte aplikaci a podívejte se, jak přidáváte produkty do nákupního košíku.
Stisknutím klávesy F5 spusťte aplikaci.
Po opětovném vytvoření databáze v projektu se otevře prohlížeč a zobrazí se stránka Default.aspx .V navigační nabídce kategorií vyberte Auta .
Na stránce ProductList.aspx se zobrazí pouze produkty zahrnuté v kategorii Auta.Klikněte na odkaz Přidat do košíku vedle prvního uvedeného produktu (kabriolet).
Zobrazí se stránka ShoppingCart.aspx zobrazující výběr v nákupním košíku.Další produkty můžete zobrazit výběrem možnosti Roviny z navigační nabídky kategorií.
Klikněte na odkaz Přidat do košíku vedle prvního uvedeného produktu.
Stránka ShoppingCart.aspx se zobrazí s další položkou.Zavřete prohlížeč.
Výpočet a zobrazení celkové objednávky
Kromě přidávání produktů do nákupního košíku přidáte do třídy metodu GetTotal
ShoppingCart
a zobrazíte celkovou částku objednávky na stránce nákupního košíku.
V Průzkumník řešení otevřete soubor ShoppingCartActions.cs ve složce Logika.
Přidejte do třídy žlutě zvýrazněnou následující
GetTotal
metoduShoppingCart
, aby se třída zobrazila takto: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
Nejprve metoda získá ID nákupního košíku pro uživatele. Pak metoda získá celkový počet košíku vynásobením ceny produktu množstvím produktu pro každý produkt uvedený v košíku.
Poznámka
Výše uvedený kód používá typ "int?
" s možnou hodnotou null. Typy s možnou hodnotou null mohou představovat všechny hodnoty základního typu a také jako hodnotu null. Další informace najdete v tématu Použití typů s možnou hodnotou null.
Úprava zobrazení nákupního košíku
Dále upravíte kód stránky ShoppingCart.aspx tak, aby volal metodu GetTotal
a zobrazil tento součet na stránce ShoppingCart.aspx , když se stránka načte.
V Průzkumník řešení klikněte pravým tlačítkem na stránku ShoppingCart.aspx a vyberte Zobrazit kód.
V souboru ShoppingCart.aspx.cs aktualizujte obslužnou rutinu
Page_Load
přidáním následujícího kódu zvýrazněného žlutě: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(); } } }
Když se stránka ShoppingCart.aspx načte, načte objekt nákupního košíku a pak načte celkový součet nákupního ShoppingCart
košíku voláním GetTotal
metody třídy. Pokud je nákupní košík prázdný, zobrazí se zpráva.
Testování nákupního košíku celkem
Spuštěním aplikace teď zjistíte, jak můžete nejen přidat produkt do nákupního košíku, ale zobrazit celkový počet nákupních košíků.
Stisknutím klávesy F5 spusťte aplikaci.
Prohlížeč se otevře a zobrazí stránku Default.aspx .V navigační nabídce kategorií vyberte Auta .
Klikněte na odkaz Přidat do košíku vedle prvního produktu.
Zobrazí se stránka ShoppingCart.aspx s celkovým součtem objednávky.Přidejte do košíku některé další produkty (například letadlo).
Stránka ShoppingCart.aspx se zobrazí s aktualizovaným součtem všech produktů, které jste přidali.
Zavřením okna prohlížeče zastavte spuštěnou aplikaci.
Přidání tlačítek Aktualizace a Pokladna do nákupního košíku
Pokud chcete uživatelům povolit úpravy nákupního košíku, přidáte na stránku nákupního košíku tlačítko Aktualizovat a tlačítko Pokladna . Tlačítko Rezervovat se používá až později v této sérii kurzů.
V Průzkumník řešení otevřete stránku ShoppingCart.aspx v kořenovém adresáři projektu webové aplikace.
Pokud chcete přidat tlačítko Aktualizovat a tlačítko Pokladna na stránku ShoppingCart.aspx , přidejte žlutě zvýrazněné značky do existující značky, jak je znázorněno v následujícím kódu:
<%@ 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>
Když uživatel klikne na tlačítko Aktualizovat , UpdateBtn_Click
bude volána obslužná rutina události. Tato obslužná rutina události zavolá kód, který přidáte v dalším kroku.
Dále můžete aktualizovat kód obsažený v souboru ShoppingCart.aspx.cs , který bude procházet položky košíku a volat RemoveItem
metody a UpdateItem
.
V Průzkumník řešení otevřete soubor ShoppingCart.aspx.cs v kořenovém adresáři projektu webové aplikace.
Do souboru ShoppingCart.aspx.cs přidejte následující oddíly kódu zvýrazněné žlutě:
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(); } } }
Když uživatel klikne na tlačítko Aktualizovat na stránce ShoppingCart.aspx , je volána metoda UpdateCartItems. Metoda UpdateCartItems získá aktualizované hodnoty pro každou položku v nákupním košíku. Pak metoda UpdateCartItems zavolá metodu UpdateShoppingCartDatabase
(přidanou a vysvětlenou v dalším kroku), která přidá nebo odebere položky z nákupního košíku. Jakmile byla databáze aktualizována tak, aby odrážela aktualizace nákupního košíku, gridView ovládací prvek je aktualizován na stránce nákupního košíku DataBind
voláním metody pro GridView. Také se aktualizuje celková částka objednávky na stránce nákupního košíku, aby odrážela aktualizovaný seznam položek.
Aktualizace a odebrání položek nákupního košíku
Na stránce ShoppingCart.aspx uvidíte, že byly přidány ovládací prvky pro aktualizaci množství položky a odebrání položky. Teď přidejte kód, který zajistí, aby tyto ovládací prvky fungovaly.
V Průzkumník řešení otevřete soubor ShoppingCartActions.cs ve složce Logic.
Do souboru třídy ShoppingCartActions.cs přidejte následující kód zvýrazněný žlutě:
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; } } }
Metoda UpdateShoppingCartDatabase
, volaná z UpdateCartItems
metody na stránce ShoppingCart.aspx.cs , obsahuje logiku pro aktualizaci nebo odebrání položek z nákupního košíku. Metoda UpdateShoppingCartDatabase
iteruje všechny řádky v seznamu nákupního košíku. Pokud byla položka nákupního košíku označena k odebrání nebo pokud je množství menší než jedna, RemoveItem
je volána metoda . V opačném případě se při zavolání metody vyhledá aktualizace položky nákupního košíku UpdateItem
. Po odebrání nebo aktualizaci položky nákupního košíku se změny databáze uloží.
Struktura ShoppingCartUpdates
slouží k uložení všech položek nákupního košíku. Metoda UpdateShoppingCartDatabase
používá ShoppingCartUpdates
strukturu k určení, zda je třeba některé položky aktualizovat nebo odebrat.
V dalším kurzu použijete metodu EmptyCart
k vymazání nákupního košíku po zakoupení produktů. Prozatím ale použijete metodu GetCount
, kterou jste právě přidali do souboru ShoppingCartActions.cs , abyste zjistili, kolik položek je v nákupním košíku.
Přidání čítače nákupního košíku
Pokud chcete uživateli povolit zobrazení celkového počtu položek v nákupním košíku, přidáte na stránku Site.Master čítač. Tento čítač bude také fungovat jako odkaz na nákupní košík.
V Průzkumník řešení otevřete stránku Site.Master.
Upravte značky přidáním odkazu na čítač nákupního košíku, jak je znázorněno žlutě, do navigačního oddílu tak, aby se zobrazoval takto:
<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"> </a></li> </ul>
Dále aktualizujte kód na pozadí souboru Site.Master.cs přidáním kódu zvýrazněného žlutě následujícím způsobem:
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(); } } }
Před vykreslení stránky jako HTML je Page_PreRender
vyvolána událost. V obslužné rutině Page_PreRender
je celkový počet nákupního košíku určen voláním GetCount
metody . Vrácená hodnota se přidá do rozsahu cartCount
zahrnutého ve značkách stránky Site.Master . Značky <span>
umožňují správné vykreslení vnitřních prvků. Když se zobrazí jakákoli stránka webu, zobrazí se celkový počet nákupního košíku. Uživatel může také kliknout na celkový počet nákupního košíku a zobrazit nákupní košík.
Testování dokončeného nákupního košíku
Aplikaci teď můžete spustit a zjistit, jak můžete přidávat, odstraňovat a aktualizovat položky v nákupním košíku. Celková hodnota nákupního košíku bude odrážet celkové náklady na všechny položky v nákupním košíku.
Stisknutím klávesy F5 spusťte aplikaci.
Prohlížeč se otevře a zobrazí stránku Default.aspx .V navigační nabídce kategorií vyberte Auta .
Klikněte na odkaz Přidat do košíku vedle prvního produktu.
Zobrazí se stránka ShoppingCart.aspx s celkovým součtem objednávky.V navigační nabídce kategorií vyberte Roviny .
Klikněte na odkaz Přidat do košíku vedle prvního produktu.
Nastavte množství první položky v nákupním košíku na 3 a zaškrtněte políčko Odebrat položku u druhé položky.
Kliknutím na tlačítko Aktualizovat aktualizujte stránku nákupního košíku a zobrazte celkovou novou objednávku.
Souhrn
V tomto kurzu jste vytvořili nákupní košík pro ukázkovou aplikaci Wingtip Toys Web Forms. V tomto kurzu jste použili Entity Framework Code First, datové poznámky, ovládací prvky dat silného typu a vazbu modelu.
Nákupní košík podporuje přidávání, odstraňování a aktualizaci položek, které uživatel vybral k nákupu. Kromě implementace funkce nákupního košíku jste se naučili, jak zobrazit položky nákupního košíku v ovládacím prvku GridView a vypočítat celkový počet objednávek.
Abyste pochopili, jak popsané funkce fungují ve skutečné obchodní aplikaci, můžete si prohlédnout příklad nopCommerce – ASP.NET založeného open source nákupním košíku pro elektronické obchodování. Původně byla postavena na Web Forms a v průběhu let se přesunula do MVC a nyní do ASP.NET Core.