Carrello acquisti
di Erik Reitan
Scaricare il progetto di esempio Wingtip Toys (C#) o scaricare e-book (PDF)
Questa serie di esercitazioni illustra le nozioni di base per la creazione di un'applicazione Web Forms ASP.NET usando ASP.NET 4.5 e Microsoft Visual Studio Express 2013 per Web. Per questa serie di esercitazioni è disponibile un progetto di Visual Studio 2013 con codice sorgente C#.
Questa esercitazione descrive la logica di business necessaria per aggiungere un carrello acquisti all'applicazione wingtip Toys di esempio Web Forms ASP.NET. Questa esercitazione si basa sull'esercitazione precedente "Visualizzare elementi di dati e dettagli" ed è parte della serie di esercitazioni Wingtip Toy Store. Al termine di questa esercitazione, gli utenti dell'app di esempio potranno aggiungere, rimuovere e modificare i prodotti nel carrello acquisti.
Contenuto dell'esercitazione:
- Come creare un carrello acquisti per l'applicazione Web.
- Come consentire agli utenti di aggiungere articoli al carrello acquisti.
- Come aggiungere un controllo GridView per visualizzare i dettagli del carrello acquisti.
- Come calcolare e visualizzare il totale dell'ordine.
- Come rimuovere e aggiornare gli articoli nel carrello acquisti.
- Come includere un contatore del carrello acquisti.
Funzionalità del codice in questa esercitazione:
- Entity Framework Code First
- Annotazioni dei dati
- Controlli dati fortemente tipizzato
- Associazione di modelli
Creazione di un carrello acquisti
In precedenza in questa serie di esercitazioni sono state aggiunte pagine e codice per visualizzare i dati del prodotto da un database. In questa esercitazione verrà creato un carrello acquisti per gestire i prodotti che gli utenti sono interessati all'acquisto. Gli utenti potranno esplorare e aggiungere articoli al carrello anche se non sono registrati o connessi. Per gestire l'accesso al carrello acquisti, si assegnerà agli utenti un identificatore univoco globale ID
(GUID) quando l'utente accede al carrello acquisti per la prima volta. Verrà archiviato ID
usando lo stato della sessione ASP.NET.
Nota
Lo stato della sessione ASP.NET è una posizione comoda per archiviare informazioni specifiche dell'utente che scadono dopo che l'utente lascia il sito. Anche se l'uso improprio dello stato sessione può avere implicazioni sulle prestazioni nei siti più grandi, l'uso leggero dello stato della sessione funziona bene a scopo dimostrativo. Il progetto di esempio Wingtip Toys mostra come usare lo stato della sessione senza un provider esterno, in cui lo stato della sessione viene archiviato in-process nel server Web che ospita il sito. Per siti di dimensioni maggiori che forniscono più istanze di un'applicazione o per siti che eseguono più istanze di un'applicazione in server diversi, prendere in considerazione l'uso del servizio Cache di Windows Azure. Questo servizio cache fornisce un servizio di memorizzazione nella cache distribuita esterno al sito Web e risolve il problema di usare lo stato della sessione in-process. Per altre informazioni, vedere How to Use ASP.NET Session State with Windows Azure Web Sites .For more information see How to Use ASP.NET Session State with Windows Azure Web Sites.
Aggiungere CartItem come classe di modello
In precedenza in questa serie di esercitazioni è stato definito lo schema per la categoria e i dati del prodotto creando le Category
classi e Product
nella cartella Models . Aggiungere ora una nuova classe per definire lo schema per il carrello acquisti. Più avanti in questa esercitazione si aggiungerà una classe per gestire l'accesso ai dati alla CartItem
tabella. Questa classe fornirà la logica di business per aggiungere, rimuovere e aggiornare gli elementi nel carrello acquisti.
Fare clic con il pulsante destro del mouse sulla cartella Models e scegliere Aggiungi ->Nuovo elemento.
La finestra di dialogo Aggiungi nuovo elemento viene visualizzata. Selezionare Codice e quindi Classe.
Denominare questa nuova classe CartItem.cs.
Scegliere Aggiungi.
Il nuovo file di classe viene visualizzato nell'editor.Sostituire il codice predefinito con il codice seguente:
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; } } }
La CartItem
classe contiene lo schema che definirà ogni prodotto che un utente aggiunge al carrello acquisti. Questa classe è simile alle altre classi di schema create in precedenza in questa serie di esercitazioni. Per convenzione, Entity Framework Code First prevede che la chiave primaria per la CartItem
tabella sia CartItemId
o ID
. Tuttavia, il codice esegue l'override del comportamento predefinito usando l'attributo di annotazione [Key]
dei dati. L'attributo Key
della proprietà ItemId specifica che la ItemID
proprietà è la chiave primaria.
La CartId
proprietà specifica l'oggetto ID
dell'utente associato all'articolo da acquistare. Si aggiungerà il codice per creare questo utente quando l'utente ID
accede al carrello acquisti. Verrà ID
archiviato anche come variabile di sessione ASP.NET.
Aggiornare il contesto del prodotto
Oltre ad aggiungere la CartItem
classe , è necessario aggiornare la classe di contesto del database che gestisce le classi di entità e che fornisce l'accesso ai dati al database. A tale scopo, si aggiungerà la classe del modello appena creata CartItem
alla ProductContext
classe .
In Esplora soluzioni trovare e aprire il file ProductContext.cs nella cartella Models.
Aggiungere il codice evidenziato al file ProductContext.cs come indicato di seguito:
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; } } }
Come accennato in precedenza in questa serie di esercitazioni, il codice nel file ProductContext.cs aggiunge lo System.Data.Entity
spazio dei nomi in modo che sia possibile accedere a tutte le funzionalità di base di Entity Framework. Questa funzionalità include la possibilità di eseguire query, inserire, aggiornare ed eliminare dati usando oggetti fortemente tipizzati. La ProductContext
classe aggiunge l'accesso alla classe del modello appena aggiunta CartItem
.
Gestione della logica di business del carrello acquisti
Successivamente, si creerà la ShoppingCart
classe in una nuova cartella logica . La ShoppingCart
classe gestisce l'accesso ai dati alla CartItem
tabella. La classe includerà anche la logica di business per aggiungere, rimuovere e aggiornare gli elementi nel carrello acquisti.
La logica del carrello acquisti che verrà aggiunta conterrà la funzionalità per gestire le azioni seguenti:
- Aggiunta di articoli al carrello acquisti
- Rimozione di articoli dal carrello acquisti
- Ottenere l'ID del carrello acquisti
- Recupero di articoli dal carrello acquisti
- Totaling the amount of all the shopping cart items
- Aggiornamento dei dati del carrello acquisti
Una pagina del carrello acquisti (ShoppingCart.aspx) e la classe del carrello acquisti verranno usate insieme per accedere ai dati del carrello acquisti. La pagina del carrello acquisti visualizzerà tutti gli elementi aggiunti dall'utente al carrello acquisti. Oltre alla pagina e alla classe del carrello acquisti, si creerà una pagina (AddToCart.aspx) per aggiungere prodotti al carrello acquisti. Si aggiungerà anche il codice alla pagina ProductList.aspx e alla pagina ProductDetails.aspx che fornirà un collegamento alla pagina AddToCart.aspx , in modo che l'utente possa aggiungere prodotti al carrello acquisti.
Il diagramma seguente illustra il processo di base che si verifica quando l'utente aggiunge un prodotto al carrello acquisti.
Quando l'utente fa clic sul collegamento Aggiungi al carrello nella pagina ProductList.aspx o nella pagina ProductDetails.aspx , l'applicazione passerà alla pagina AddToCart.aspx e quindi automaticamente alla pagina ShoppingCart.aspx . La pagina AddToCart.aspx aggiungerà il prodotto selezionato al carrello chiamando un metodo nella classe ShoppingCart. Nella pagina ShoppingCart.aspx verranno visualizzati i prodotti aggiunti al carrello acquisti.
Creazione della classe Carrello acquisti
La ShoppingCart
classe verrà aggiunta a una cartella separata nell'applicazione in modo che vi sia una chiara distinzione tra il modello (cartella Models), le pagine (cartella radice) e la logica (cartella logica).
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto WingtipToyse scegliere Aggiungi-Nuova>cartella. Assegnare alla nuova cartella il nome Logic.
Fare clic con il pulsante destro del mouse sulla cartella Logica e quindi scegliere Aggiungi ->Nuovo elemento.
Aggiungere un nuovo file di classe denominato ShoppingCartActions.cs.
Sostituire il codice predefinito con il codice seguente:
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(); } } }
Il AddToCart
metodo consente di includere singoli prodotti nel carrello acquisti in base al prodotto ID
. Il prodotto viene aggiunto al carrello o se il carrello contiene già un articolo per tale prodotto, la quantità viene incrementata.
Il GetCartId
metodo restituisce il carrello ID
per l'utente. Il carrello ID
viene usato per tenere traccia degli articoli che un utente ha nel carrello acquisti. Se l'utente non dispone di un carrello ID
esistente, viene creato un nuovo carrello ID
. Se l'utente ha eseguito l'accesso come utente registrato, il carrello ID
viene impostato sul nome utente. Tuttavia, se l'utente non ha eseguito l'accesso, il carrello ID
viene impostato su un valore univoco (GUID). Un GUID garantisce che venga creato un solo carrello per ogni utente, in base alla sessione.
Il GetCartItems
metodo restituisce un elenco di articoli del carrello acquisti per l'utente. Più avanti in questa esercitazione si noterà che l'associazione di modelli viene usata per visualizzare gli elementi del carrello nel carrello degli acquisti usando il GetCartItems
metodo .
Creazione della funzionalità Add-To-Cart
Come accennato in precedenza, si creerà una pagina di elaborazione denominata AddToCart.aspx che verrà usata per aggiungere nuovi prodotti al carrello acquisti dell'utente. Questa pagina chiamerà il AddToCart
metodo nella ShoppingCart
classe appena creata. La pagina AddToCart.aspx prevede che un prodotto ID
venga passato. Questo prodotto ID
verrà usato quando si chiama il AddToCart
metodo nella ShoppingCart
classe.
Nota
Verrà modificato il code-behind (AddToCart.aspx.cs) per questa pagina, non l'interfaccia utente della pagina (AddToCart.aspx).
Per creare la funzionalità Add-To-Cart:
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto WingtipToys, scegliere Aggiungi ->Nuovo elemento.
La finestra di dialogo Aggiungi nuovo elemento viene visualizzata.Aggiungere una nuova pagina standard (Web Form) all'applicazione denominata AddToCart.aspx.
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla pagina AddToCart.aspx e quindi scegliere Visualizza codice. Il file AddToCart.aspx.cs code-behind viene aperto nell'editor.
Sostituire il codice esistente in AddToCart.aspx.cs code-behind con quanto segue:
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"); } } }
Quando viene caricata la pagina AddToCart.aspx , il prodotto ID
viene recuperato dalla stringa di query. Successivamente, viene creata un'istanza della classe carrello acquisti e viene usata per chiamare il AddToCart
metodo aggiunto in precedenza in questa esercitazione. Il AddToCart
metodo, contenuto nel file ShoppingCartActions.cs , include la logica per aggiungere il prodotto selezionato al carrello acquisti o aumentare la quantità di prodotto del prodotto selezionato. Se il prodotto non è stato aggiunto al carrello acquisti, il prodotto viene aggiunto alla CartItem
tabella del database. Se il prodotto è già stato aggiunto al carrello acquisti e l'utente aggiunge un elemento aggiuntivo dello stesso prodotto, la quantità del prodotto viene incrementata nella CartItem
tabella. Infine, la pagina reindirizza alla pagina ShoppingCart.aspx che si aggiungerà nel passaggio successivo, in cui l'utente visualizza un elenco aggiornato di elementi nel carrello.
Come accennato in precedenza, un utente viene usato per identificare i prodotti associati a un utente ID
specifico. Viene ID
aggiunto a una riga nella CartItem
tabella ogni volta che l'utente aggiunge un prodotto al carrello acquisti.
Creazione dell'interfaccia utente del carrello acquisti
La pagina ShoppingCart.aspx visualizzerà i prodotti aggiunti all'utente al carrello acquisti. Fornisce anche la possibilità di aggiungere, rimuovere e aggiornare gli articoli nel carrello acquisti.
In Esplora soluzioni fare clic con il pulsante destro del mouse su WingtipToys, scegliere Aggiungi ->Nuovo elemento.
La finestra di dialogo Aggiungi nuovo elemento viene visualizzata.Aggiungere una nuova pagina (Web Form) che include una pagina master selezionando Web Form usando la pagina master. Assegnare un nome alla nuova pagina ShoppingCart.aspx.
Selezionare Site.Master per collegare la pagina master alla pagina aspx appena creata.
Nella pagina ShoppingCart.aspx sostituire il markup esistente con il markup seguente:
<%@ 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>
La pagina ShoppingCart.aspx include un controllo GridView denominato CartList
. Questo controllo usa l'associazione di modelli per associare i dati del carrello degli acquisti dal database al controllo GridView . Quando si imposta la ItemType
proprietà del controllo GridView , l'espressione Item
di associazione dati è disponibile nel markup del controllo e il controllo diventa fortemente tipizzato. Come accennato in precedenza in questa serie di esercitazioni, è possibile selezionare i dettagli dell'oggetto Item
usando IntelliSense. Per configurare un controllo dati per usare l'associazione di modelli per selezionare i dati, impostare la SelectMethod
proprietà del controllo. Nel markup precedente si imposta l'oggetto SelectMethod
per usare il metodo GetShoppingCartItems che restituisce un elenco di CartItem
oggetti. Il controllo dati GridView chiama il metodo al momento appropriato nel ciclo di vita della pagina e associa automaticamente i dati restituiti. Il GetShoppingCartItems
metodo deve comunque essere aggiunto.
Recupero degli articoli del carrello acquisti
Aggiungere quindi il codice all'interfaccia utente shoppingCart.aspx.cs code-behind per recuperare e popolare l'interfaccia utente del carrello acquisti.
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla pagina ShoppingCart.aspx e quindi scegliere Visualizza codice. Il file shoppingCart.aspx.cs code-behind viene aperto nell'editor.
Sostituire il codice esistente con quello seguente:
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(); } } }
Come accennato in precedenza, il GridView
controllo dati chiama il GetShoppingCartItems
metodo al momento appropriato nel ciclo di vita della pagina e associa automaticamente i dati restituiti. Il GetShoppingCartItems
metodo crea un'istanza dell'oggetto ShoppingCartActions
. Il codice usa quindi tale istanza per restituire gli elementi nel carrello chiamando il GetCartItems
metodo .
Aggiunta di prodotti al carrello acquisti
Quando viene visualizzata la pagina ProductList.aspx o ProductDetails.aspx , l'utente sarà in grado di aggiungere il prodotto al carrello acquisti usando un collegamento. Quando fanno clic sul collegamento, l'applicazione passa alla pagina di elaborazione denominata AddToCart.aspx. La pagina AddToCart.aspx chiamerà il AddToCart
metodo nella ShoppingCart
classe aggiunta in precedenza in questa esercitazione.
A questo punto, si aggiungerà un collegamento Aggiungi al carrello sia alla pagina ProductList.aspx che alla pagina ProductDetails.aspx . Questo collegamento includerà il prodotto ID
recuperato dal database.
In Esplora soluzioni trovare e aprire la pagina denominata ProductList.aspx.
Aggiungere il markup evidenziato in giallo alla pagina ProductList.aspx in modo che l'intera pagina venga visualizzata come segue:
<%@ 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>
Test del carrello acquisti
Eseguire l'applicazione per vedere come aggiungere prodotti al carrello acquisti.
Premere F5 per eseguire l'applicazione.
Dopo aver ricreato il database, il browser verrà aperto e visualizzato la pagina Default.aspx .Selezionare Auto dal menu di spostamento categoria.
Viene visualizzata la pagina ProductList.aspx che mostra solo i prodotti inclusi nella categoria "Cars".Fare clic sul collegamento Aggiungi al carrello accanto al primo prodotto elencato (auto convertibile).
Viene visualizzata la pagina ShoppingCart.aspx che mostra la selezione nel carrello acquisti.Visualizzare altri prodotti selezionando Piani dal menu di spostamento categoria.
Fare clic sul collegamento Aggiungi al carrello accanto al primo prodotto elencato.
La pagina ShoppingCart.aspx viene visualizzata con l'elemento aggiuntivo.Chiudere il browser.
Calcolo e visualizzazione del totale ordine
Oltre all'aggiunta di prodotti al carrello acquisti, si aggiungerà un GetTotal
metodo alla ShoppingCart
classe e visualizzerà l'importo totale dell'ordine nella pagina del carrello acquisti.
In Esplora soluzioni aprire il file ShoppingCartActions.cs nella cartella Logica.
Aggiungere il metodo seguente
GetTotal
evidenziato in giallo allaShoppingCart
classe, in modo che la classe venga visualizzata come segue: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; } } }
Prima di tutto, il GetTotal
metodo ottiene l'ID del carrello acquisti per l'utente. Quindi il metodo ottiene il totale del carrello moltiplicando il prezzo del prodotto per la quantità di prodotto per ogni prodotto elencato nel carrello.
Nota
Il codice precedente usa il tipo nullable "int?
". I tipi nullable possono rappresentare tutti i valori di un tipo sottostante e anche come valore Null. Per altre informazioni, vedere Uso di tipi nullable.
Modificare la visualizzazione del carrello acquisti
Successivamente si modifica il codice per la pagina ShoppingCart.aspx per chiamare il metodo e visualizzare il GetTotal
totale nella pagina ShoppingCart.aspx quando la pagina viene caricata.
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla pagina ShoppingCart.aspx e scegliere Visualizza codice.
Nel file ShoppingCart.aspx.cs aggiornare il gestore aggiungendo il
Page_Load
codice seguente evidenziato in giallo: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(); } } }
Quando la pagina ShoppingCart.aspx viene caricata, carica l'oggetto carrello acquisti e quindi recupera il totale del carrello chiamando il GetTotal
metodo della ShoppingCart
classe. Se il carrello acquisti è vuoto, viene visualizzato un messaggio a tale effetto.
Test del totale del carrello acquisti
Eseguire l'applicazione ora per vedere come è possibile aggiungere un prodotto al carrello acquisti, ma è possibile visualizzare il totale del carrello acquisti.
Premere F5 per eseguire l'applicazione.
Si aprirà il browser e verrà visualizzata la pagina Default.aspx .Selezionare Auto dal menu di spostamento categoria.
Fare clic sul collegamento Aggiungi al carrello accanto al primo prodotto.
La pagina ShoppingCart.aspx viene visualizzata con il totale dell'ordine.Aggiungere alcuni altri prodotti (ad esempio un piano) al carrello.
La pagina ShoppingCart.aspx viene visualizzata con un totale aggiornato per tutti i prodotti aggiunti.
Arrestare l'app in esecuzione chiudendo la finestra del browser.
Aggiunta di pulsanti di aggiornamento e pagamento al carrello acquisti
Per consentire agli utenti di modificare il carrello acquisti, si aggiungerà un pulsante Aggiorna e un pulsante Di pagamento alla pagina del carrello acquisti. Il pulsante Checkout non viene usato fino a quando non viene usato più avanti in questa serie di esercitazioni.
In Esplora soluzioni aprire la pagina ShoppingCart.aspx nella radice del progetto applicazione Web.
Per aggiungere il pulsante Aggiorna e il pulsante Checkout alla pagina ShoppingCart.aspx , aggiungere il markup evidenziato in giallo al markup esistente, come illustrato nel codice seguente:
<%@ 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>
Quando l'utente fa clic sul pulsante Aggiorna , verrà chiamato il UpdateBtn_Click
gestore eventi. Questo gestore eventi chiamerà il codice che verrà aggiunto nel passaggio successivo.
È quindi possibile aggiornare il codice contenuto nel file ShoppingCart.aspx.cs per eseguire il ciclo degli elementi del carrello e chiamare i RemoveItem
metodi e UpdateItem
.
In Esplora soluzioni aprire il file ShoppingCart.aspx.cs nella radice del progetto dell'applicazione Web.
Aggiungere le sezioni di codice seguenti evidenziate in giallo al file 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(); } } }
Quando l'utente fa clic sul pulsante Update nella pagina ShoppingCart.aspx , viene chiamato il metodo UpdateCartItems. Il metodo UpdateCartItems ottiene i valori aggiornati per ogni elemento nel carrello acquisti. Il metodo UpdateCartItems chiama quindi il UpdateShoppingCartDatabase
metodo (aggiunto e spiegato nel passaggio successivo) per aggiungere o rimuovere elementi dal carrello acquisti. Dopo aver aggiornato il database per riflettere gli aggiornamenti del carrello acquisti, il controllo GridView viene aggiornato nella pagina del carrello acquisti chiamando il DataBind
metodo per GridView. Inoltre, l'importo totale dell'ordine nella pagina del carrello acquisti viene aggiornato per riflettere l'elenco aggiornato di articoli.
Aggiornamento e rimozione di articoli del carrello acquisti
Nella pagina ShoppingCart.aspx è possibile visualizzare i controlli aggiunti per aggiornare la quantità di un elemento e rimuovere un elemento. Aggiungere ora il codice che farà funzionare questi controlli.
In Esplora soluzioni aprire il file ShoppingCartActions.cs nella cartella Logica.
Aggiungere il codice seguente evidenziato in giallo al file di classe 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; } } }
Il UpdateShoppingCartDatabase
metodo, chiamato dal UpdateCartItems
metodo nella pagina ShoppingCart.aspx.cs , contiene la logica per aggiornare o rimuovere elementi dal carrello acquisti. Il UpdateShoppingCartDatabase
metodo esegue l'iterazione di tutte le righe all'interno dell'elenco dei carrello acquisti. Se un articolo del carrello acquisti è stato contrassegnato per essere rimosso o la quantità è minore di una, viene chiamato il RemoveItem
metodo. In caso contrario, l'elemento del carrello acquisti viene controllato per gli aggiornamenti quando viene chiamato il UpdateItem
metodo. Dopo aver rimosso o aggiornato l'elemento del carrello acquisti, le modifiche al database vengono salvate.
La ShoppingCartUpdates
struttura viene usata per contenere tutti gli articoli del carrello acquisti. Il UpdateShoppingCartDatabase
metodo usa la ShoppingCartUpdates
struttura per determinare se uno degli elementi deve essere aggiornato o rimosso.
Nell'esercitazione successiva si userà il metodo per cancellare il EmptyCart
carrello acquisti dopo l'acquisto di prodotti. Ma per il momento, si userà il metodo appena aggiunto al file ShoppingCartActions.cs per determinare il GetCount
numero di articoli nel carrello acquisti.
Aggiunta di un contatore del carrello acquisti
Per consentire all'utente di visualizzare il numero totale di articoli nel carrello acquisti, si aggiungerà un contatore alla pagina Site.Master . Questo contatore fungerà anche da collegamento al carrello acquisti.
In Esplora soluzioni aprire la pagina Site.Master.
Modificare il markup aggiungendo il collegamento del contatore del carrello acquisti come illustrato in giallo alla sezione di spostamento in modo che venga visualizzato come segue:
<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>
Aggiornare quindi il code-behind del file Site.Master.cs aggiungendo il codice evidenziato in giallo come segue:
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(); } } }
Prima di eseguire il rendering della pagina come HTML, viene generato l'evento Page_PreRender
. Page_PreRender
Nel gestore il conteggio totale del carrello acquisti è determinato chiamando il GetCount
metodo . Il valore restituito viene aggiunto all'intervallo cartCount
incluso nel markup della pagina Site.Master . I <span>
tag consentono il rendering corretto degli elementi interni. Quando viene visualizzata una pagina del sito, verrà visualizzato il totale del carrello acquisti. L'utente può anche fare clic sul carrello acquisti totale per visualizzare il carrello acquisti.
Test del carrello acquisti completato
È possibile eseguire l'applicazione ora per vedere come aggiungere, eliminare e aggiornare gli elementi nel carrello acquisti. Il totale del carrello degli acquisti rifletterà il costo totale di tutti gli articoli nel carrello acquisti.
Premere F5 per eseguire l'applicazione.
Il browser viene aperto e mostra la pagina Default.aspx .Selezionare Auto dal menu di spostamento categoria.
Fare clic sul collegamento Aggiungi al carrello accanto al primo prodotto.
La pagina ShoppingCart.aspx viene visualizzata con il totale dell'ordine.Selezionare Piani dal menu di spostamento categoria.
Fare clic sul collegamento Aggiungi al carrello accanto al primo prodotto.
Impostare la quantità del primo elemento nel carrello acquisti su 3 e selezionare la casella di controllo Rimuovi elemento del secondo elemento.
Fare clic sul pulsante Aggiorna per aggiornare la pagina del carrello acquisti e visualizzare il nuovo ordine totale.
Riepilogo
In questa esercitazione è stato creato un carrello acquisti per l'applicazione di esempio Wingtip Toys Web Forms. Durante questa esercitazione è stato usato Entity Framework Code First, annotazioni dei dati, controlli dati fortemente tipizzato e associazione di modelli.
Il carrello acquisti supporta l'aggiunta, l'eliminazione e l'aggiornamento degli elementi selezionati dall'utente per l'acquisto. Oltre a implementare la funzionalità del carrello acquisti, si è appreso come visualizzare gli articoli del carrello acquisti in un controllo GridView e calcolare il totale dell'ordine.
Per comprendere come funziona la funzionalità descritta in un'applicazione aziendale reale, è possibile visualizzare l'esempio di nopCommerce - ASP.NET basato open source carrello acquisti eCommerce. Originariamente, è stato costruito su Web Forms e nel corso degli anni è stato spostato in MVC e ora in ASP.NET Core.