Shopping Cart in ASP.NET

Build a Shopping Cart in ASP.NET

Shopping carts are very important and can many times be the most intimidating part of building an e-commerce site. This tutorial will show how easy it can be to implement a shopping cart using ASP.NET. Additionally, several basic explanations will be provided to help beginning ASP.NET programmers understand this wonderful framework.

Quick Overview of ASP.NET

Since ASP.NET hasn’t been covered too much on NETTUTS, I thought it would be good to include a brief overview of some of the things that distinguish it from other languages.

  1. Code is compiled. The first time an ASP.NET page is requested over the web, the code is compiled into one or more DLL files on the server. This gives you the ability to just copy code out to the server and it gives you the speed benefit of compiled code.
  2. ASP.NET is an object oriented framework. Every function, property and page is part of a class. For example, each web page is its own class that extends the Page class. The Page class has an event that is fired when the webpage is loaded called the “Page Load Event”. You can write a function that subscribes to that event and is called on. The same principle applies to other events like the button click and “drop-down” “selected index changed” events.
  3. The logic is separate from the design and content. They interact with each other, but they are in separate places. Generally, this allows a designer to design without worrying about function and it allows the programmer to focus on function without looking at the design. You have the choice of putting them both in the same file or in different files. This is similar to model-view-controller model.

If you are new to ASP.NET (and you have Windows), you can try it out for free You can download Visual Studio Express by visiting the ASP.NET website. Also, when you create a website locally on your machine, you can run the website at any time and Visual Studio will quickly start a server on your computer and pull up your website in your default browser.

Step 1: Create the ShoppingCart Class

We need a place to store the items in the shopping cart as well as functions to manipulate the items. We’ll create a ShoppingCart class for this. This class will also manage session storage.

First, we have to create the App_Code folder. To do this, go to the “Website” menu, then “Add ASP.NET Folder”, and choose “App_Code.” This is where we’ll put all of our custom classes. These classes will automatically be accessible from the code in any of our pages (we don’t need to reference it using something similar to “include” or anything). Then we can add a class to that folder by right-clicking on the folder and choosing “Add New Item.”

Quick Tip: Regions in ASP.NET are really nice to organize and group code together. The nicest thing about them is that you can open and close regions to minimize the amount of code that you are looking at or quickly find your way around a file.

using System.Collections.Generic;
using System.Web;

/**
 * The ShoppingCart class
 *
 * Holds the items that are in the cart and provides methods for their manipulation
 */
public class ShoppingCart {
    #region Properties

    public List<CartItem> Items { get; private set; }

    #endregion

    #region Singleton Implementation

    // Readonly properties can only be set in initialization or in a constructor
    public static readonly ShoppingCart Instance;

    // The static constructor is called as soon as the class is loaded into memory
    static ShoppingCart() {
        // If the cart is not in the session, create one and put it there
        // Otherwise, get it from the session
        if (HttpContext.Current.Session["ASPNETShoppingCart"] == null) {
            Instance = new ShoppingCart();
            Instance.Items = new List<CartItem>();
            HttpContext.Current.Session["ASPNETShoppingCart"] = Instance;
        } else {
            Instance = (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];
        }
    }

    // A protected constructor ensures that an object can't be created from outside
    protected ShoppingCart() { }

    #endregion

    #region Item Modification Methods
    /**
     * AddItem() - Adds an item to the shopping
     */
    public void AddItem(int productId) {
        // Create a new item to add to the cart
        CartItem newItem = new CartItem(productId);

        // If this item already exists in our list of items, increase the quantity
        // Otherwise, add the new item to the list
        if (Items.Contains(newItem)) {
            foreach (CartItem item in Items) {
                if (item.Equals(newItem)) {
                    item.Quantity++;
                    return;
                }
            }
        } else {
            newItem.Quantity = 1;
            Items.Add(newItem);
        }
    }

    /**
     * SetItemQuantity() - Changes the quantity of an item in the cart
     */
    public void SetItemQuantity(int productId, int quantity) {
        // If we are setting the quantity to 0, remove the item entirely
        if (quantity == 0) {
            RemoveItem(productId);
            return;
        }

        // Find the item and update the quantity
        CartItem updatedItem = new CartItem(productId);

        foreach (CartItem item in Items) {
            if (item.Equals(updatedItem)) {
                item.Quantity = quantity;
                return;
            }
        }
    }

    /**
     * RemoveItem() - Removes an item from the shopping cart
     */
    public void RemoveItem(int productId) {
        CartItem removedItem = new CartItem(productId);
        Items.Remove(removedItem);
    }
    #endregion

    #region Reporting Methods
    /**
     * GetSubTotal() - returns the total price of all of the items
     *                 before tax, shipping, etc.
     */
    public decimal GetSubTotal() {
        decimal subTotal = 0;
        foreach (CartItem item in Items)
            subTotal += item.TotalPrice;

        return subTotal;
    }
    #endregion
}

Step 2: The CartItem & Product Classes

With a place to store our shopping cart items, we need to be able to store information about each item. We’ll create a CartItem class that will do this. We’ll also create a simple Product class that will simulate a way to grab data about the products we’re selling.

The CartItem class:

using System;

/**
 * The CartItem Class
 *
 * Basically a structure for holding item data
 */
public class CartItem : IEquatable<CartItem> {
    #region Properties

    // A place to store the quantity in the cart
    // This property has an implicit getter and setter.
    public int Quantity { get; set; }

    private int _productId;
    public int ProductId {
        get { return _productId; }
        set {
            // To ensure that the Prod object will be re-created
            _product = null;
            _productId = value;
        }
    }

    private Product _product = null;
    public Product Prod {
        get {
            // Lazy initialization - the object won't be created until it is needed
            if (_product == null) {
                _product = new Product(ProductId);
            }
            return _product;
        }
    }

    public string Description {
        get { return Prod.Description; }
    }

    public decimal UnitPrice {
        get { return Prod.Price; }
    }

    public decimal TotalPrice {
        get { return UnitPrice * Quantity; }
    }

    #endregion

    // CartItem constructor just needs a productId
    public CartItem(int productId) {
        this.ProductId = productId;
    }

    /**
     * Equals() - Needed to implement the IEquatable interface
     *    Tests whether or not this item is equal to the parameter
     *    This method is called by the Contains() method in the List class
     *    We used this Contains() method in the ShoppingCart AddItem() method
     */
    public bool Equals(CartItem item) {
        return item.ProductId == this.ProductId;
    }
}

The Product class:

/**
 * The Product class
 *
 * This is just to simulate some way of accessing data about  our products
 */
public class Product
{

    public int Id { get; set; }
    public decimal Price { get; set; }
    public string Description { get; set; }

    public Product(int id)
    {
        this.Id = id;
        switch (id) {
            case 1:
                this.Price = 19.95m;
                this.Description = "Shoes";
                break;
            case 2:
                this.Price = 9.95m;
                this.Description = "Shirt";
                break;
            case 3:
                this.Price = 14.95m;
                this.Description = "Pants";
                break;
        }
    }

}

Definition: A “property” in ASP.NET is a variable in a class that has a setter, a getter, or both. This is similar to other languages, but in ASP.NET, the word property refers specifically to this. An example of this is the ProductId property in the CartItem class. It is not simply a variable in a class with a method to get or set it. It is declared in a special way with get{} and set{} blocks.

Let’s Add Items to the Cart

After having our heads in the code for so long, it’s time we do something visual. This page will simply be a way to add items to the cart. All we need is a few items with “Add to Cart” links. Let’s put this code in the Default.aspx page.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>My Store</title>
    <link href="Styles/StyleSheet.css" rel="stylesheet" type="text/css" />
</head>
<body>

    <form id="form1" runat="server">

        <div class="container">
            <h1>My Store</h1>

            <div class="products">
                <div>Shoes - <asp:LinkButton runat="server" ID="btnAddShirt" OnClick="btnAddShoes_Click">Add To Cart</asp:LinkButton></div>

                <div>Shirt - <asp:LinkButton runat="server" ID="btnAddShorts" OnClick="btnAddShirt_Click">Add To Cart</asp:LinkButton></div>
                <div>Pants - <asp:LinkButton runat="server" ID="btnAddShoes" OnClick="btnAddPants_Click">Add To Cart</asp:LinkButton></div>
            </div>

            <a href="ViewCart.aspx">View Cart</a>
        </div>

    </form>
</body>
</html>

As you can see, the only thing happening here is that we have a few LinkButtons that have OnClick event handlers associated to them.

In the code-behind page, we have 4 event handlers. We have one for each LinkButton that just adds an item to the shopping cart and redirects the user to view their cart. We also have a Page_Load event handler which is created by the IDE by default that we didn’t need to use.

using System;

public partial class _Default : System.Web.UI.Page {
    protected void Page_Load(object sender, EventArgs e) {

    }

    protected void btnAddShoes_Click(object sender, EventArgs e) {
        // Add product 1 to the shopping cart
        ShoppingCart.Instance.AddItem(1);

        // Redirect the user to view their shopping cart
        Response.Redirect("ViewCart.aspx");
    }

    protected void btnAddShirt_Click(object sender, EventArgs e) {
        ShoppingCart.Instance.AddItem(2);
        Response.Redirect("ViewCart.aspx");
    }

    protected void btnAddPants_Click(object sender, EventArgs e) {
        ShoppingCart.Instance.AddItem(3);
        Response.Redirect("ViewCart.aspx");
    }

}

Build the Shopping Cart Page

Finally, what we’ve been preparing for the whole time—the shopping cart! Let’s just look at ViewCart.aspx first and I’ll explain it after that.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ViewCart.aspx.cs" Inherits="ViewCart" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Shopping Cart</title>
    <link href="Styles/StyleSheet.css" rel="stylesheet" type="text/css" />
</head>
<body>

    <form id="form1" runat="server">
        <div class="container">
            <h1>Shopping Cart</h1>
            <a href="Default.aspx">< Back to Products</a>

            <br /><br />
            <asp:GridView runat="server" ID="gvShoppingCart" AutoGenerateColumns="false" EmptyDataText="There is nothing in your shopping cart." GridLines="None" Width="100%" CellPadding="5" ShowFooter="true" DataKeyNames="ProductId" OnRowDataBound="gvShoppingCart_RowDataBound" OnRowCommand="gvShoppingCart_RowCommand">
                <HeaderStyle HorizontalAlign="Left" BackColor="#3D7169" ForeColor="#FFFFFF" />
                <FooterStyle HorizontalAlign="Right" BackColor="#6C6B66" ForeColor="#FFFFFF" />
                <AlternatingRowStyle BackColor="#F8F8F8" />
                <Columns>

                    <asp:BoundField DataField="Description" HeaderText="Description" />
                    <asp:TemplateField HeaderText="Quantity">
                        <ItemTemplate>
                            <asp:TextBox runat="server" ID="txtQuantity" Columns="5" Text='<%# Eval("Quantity") %>'></asp:TextBox><br />
                            <asp:LinkButton runat="server" ID="btnRemove" Text="Remove" CommandName="Remove" CommandArgument='<%# Eval("ProductId") %>' style="font-size:12px;"></asp:LinkButton>

                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField DataField="UnitPrice" HeaderText="Price" ItemStyle-HorizontalAlign="Right" HeaderStyle-HorizontalAlign="Right" DataFormatString="{0:C}" />
                    <asp:BoundField DataField="TotalPrice" HeaderText="Total" ItemStyle-HorizontalAlign="Right" HeaderStyle-HorizontalAlign="Right" DataFormatString="{0:C}" />
                </Columns>
            </asp:GridView>

            <br />
            <asp:Button runat="server" ID="btnUpdateCart" Text="Update Cart" OnClick="btnUpdateCart_Click" />
        </div>
    </form>
</body>
</html>

The GridView control is a powerful control that can seem complicated at first. I won’t discuss the style elements because they are self-explanatory. (There are some principles here that I’m not going to explain in depth. I am just going to try to get the main idea across). Let’s break it down.

  • Giving the GridView an ID will allow us to access the GridView from the code-behind using that ID.

    ID="gvShoppingCart"
  • The GridView will automatically generate columns and column names from the data that we supply unless we specifically tell it not to.

    AutoGenerateColumns="false"
  • We can tell the GridView what to display in case we supply it with no data.

    EmptyDataText="There is nothing in your shopping cart."
  • We want to show the footer so that we can display the total price.

    ShowFooter="true"
  • It will be nice for us to have an array of ProductIds indexed by the row index when we are updating the quantity of a cart item in the code-behind. This will do that for us:

    DataKeyNames="ProductId"
  • We need events to respond to two events: RowDataBound and RowCommand. Basically, RowDataBound is fired when the GridView takes a row of our data and adds it to the table. We are only using this event to respond to the footer being bound so that we can customize what we want displayed there. RowCommand is fired when a link or a button is clicked from inside the GridView. In this case, it is the “Remove” link.

    OnRowDataBound="gvShoppingCart_RowDataBound" OnRowCommand="gvShoppingCart_RowCommand"

Now let’s talk about the columns. We define the columns here and the GridView will take every row in the data that we supply and map the data in that row to the column that it should display in. The simplest column is the BoundField. In our case, it is going to look for a “Description” property in our CartItem object and display it in the first column. The header for that column will also display “Description.”

We needed the quantity to display inside a textbox rather than just displaying as text, so we used a TemplateField. The TemplateField allows you to put whatever you want in that column. If you need some data from the row, you just insert <%# Eval(“PropertyName”) %>. The LinkButton that we put in our TemplateField has a CommandName and a CommandArgument, both of which will be passed to our GridView’s RowCommand event handler.

The last thing worth mentioning here is that the last two BoundFields have a DataFormatString specified. This is just one of the many format strings that ASP.NET provides. This one formats the number as a currency. See the Microsoft documentation for other format strings.

Now we can look at the code-behind page. I have supplied lots of comments here to describe what is happening.

The End Result:

Now we have a nice working shopping cart!

You Also Might Like…

Screencast

How to Search a Website Using ASP.NET 3.5 – screencast

Oct 1st in Screencasts by Jeffrey Way

56

I’m happy to say that today, we are posting our very first article on ASP.NET. In this screencast, I’ll show you how to implement a simple search functionality into your personal website. We’ll go over many of the new features in ASP.NET 3.5, such as LINQ and many of the AJAX controls that ship with Visual Studio/Web Developer.

Continue Reading

  • Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.


Add Comment

Discussion 140 Comments

Comment Page 2 of 3 1 2 3
  1. Shafiur Rahman says:

    Hi

    Please suggest me how to bind the data bethought singleton.
    Code is given below.
    public static ShoppingCart GetShoppingCart() {
    // If the cart is not in the session, create one and put it there
    if (HttpContext.Current.Session["ASPNETShoppingCart"] == null) {
    ShoppingCart cart = new ShoppingCart();
    cart.Items = new List();
    HttpContext.Current.Session["ASPNETShoppingCart"] = cart;
    }

    return (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];
    }

    Then, every time that you need to access it, replace this:

    ShoppingCart.Instance.AddItem(1);

    with this:

    ShoppingCart cart = ShoppingCart.getShoppingCart();
    cart.AddItem(1);

    kind regards

  2. asdas says:

    not working even with singleton cut…

  3. hainv says:

    good code !Are you think that we are save Cart Items to Cookies ?

  4. hainv says:

    If do same you ,all customer will have same cart
    I’m modified:
    // The static constructor is called as soon as the class is loaded into memory
    public ShoppingCart()
    {
    // If the cart is not in the session, create one and put it there
    // Otherwise, get it from the session
    if (HttpContext.Current.Session["ShoppingCart"] == null)
    {
    _items = new List();
    HttpContext.Current.Session["ShoppingCart"] = _items;
    } else {
    _items = (List)HttpContext.Current.Session["ShoppingCart"];
    }
    }

    When you call method, you can do as :(new ShoppingCart()).Items;

    protected void BindData() {
    // Let’s give the data to the GridView and let it work!
    // The GridView will take our cart items one by one and use the properties
    // that we declared as column names (DataFields)
    gvShoppingCart.DataSource = (new ShoppingCart()).Items;
    gvShoppingCart.DataBind();
    }

  5. Jon says:

    Hello Don,

    First off, thanks for providing this tutorial it has really aided my basic understanding of how to implement a shopping cart in ASP.NET.

    I’ve been trying to get rid of the Singleton implementation with the replacement code you supplied above however I am getting an “object reference not set to an instance of an object” error when running the source. This error gets thrown on the following statement’s completion:

    “if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)”

    Here’s the modified code region that’s causing this problem

    #region New Implementation

    public static readonly ShoppingCart Instance;
    // Readonly properties can only be set in initialization or in a constructor
    public static ShoppingCart GetShoppingCart()
    {
    // If the cart is not in the session, create one and put it there
    if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)
    {
    ShoppingCart cart = new ShoppingCart();
    cart.Items = new List();
    HttpContext.Current.Session["ASPNETShoppingCart"] = cart;
    }

    return (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];
    }

    Any help is much appreciated, thanks again for the tutorial
    I’ve been unable to figure out how to fix this so any help is much appreciated.

  6. arjun says:

    Thanks, it helps really.
    But I want product list i.e ProdId,ProdName,Price from database then, how to do.
    please suggest me the way.

  7. Joel says:

    Hello Don

    Thanks , is really good

    I need to show a produt list with : Id, Name, Price, Graph, and description , do you have some samples ?

    Regards

  8. Velibor says:

    Works fine. That’s what I looking for. Maybe some AJAX in this could improve interaction without separately web page for viewing cart. Shopping cart could be visible from some pop-up window etc. :D

    Thanks for great tut.

  9. Joe says:

    I dont really use ASP that much, but still pretty cool. :P

  10. Kris Crosby says:

    To make this work with multiple users here is the complete solution to make this work for all of us who are not programmers. First in C. You need the change the following files from the example: ShoppingCart.cs per comments above. Then Default.aspx.cs per comments above. and last ViewCart.aspx.cs anytime the instance was called.

    • Kris Crosby says:

      //ViewCart.aspx.cs

      using System;
      using System.Web.UI.WebControls;
      /*************************** MEASURE LINE *****************************************/
      public partial class ViewCart : System.Web.UI.Page
      {
      protected void Page_Load(object sender, EventArgs e)
      {
      // ASP.NET keeps track of the state of all server controls
      // (like the GridView). Because of this, we don’t need to supply it with
      // the data every time the page loads. (No more re-checking checkboxes
      // that were checked or re-selecting the right item in the drop-down when
      // the page is submitted. It’s all done for you!)
      if (!IsPostBack)
      BindData();
      }

      protected void BindData()
      {
      // Let’s give the data to the GridView and let it work!
      // The GridView will take our cart items one by one and use the properties
      // that we declared as column names (DataFields)
      ShoppingCart cart = ShoppingCart.GetShoppingCart();
      gvShoppingCart.DataSource = cart.Items;
      gvShoppingCart.DataBind();
      }

      protected void gvShoppingCart_RowDataBound(object sender, GridViewRowEventArgs e) {
      // If we are binding the footer row, let’s add in our total

      if (e.Row.RowType == DataControlRowType.Footer) {
      ShoppingCart cart = ShoppingCart.GetShoppingCart();
      e.Row.Cells[3].Text = “Total: ” + cart.GetSubTotal().ToString(“C”);
      }
      }

      /**
      * This is the method that responds to the Remove button’s click event
      */
      protected void gvShoppingCart_RowCommand(object sender, GridViewCommandEventArgs e) {
      if (e.CommandName == “Remove”) {
      int productId = Convert.ToInt32(e.CommandArgument);
      ShoppingCart cart = ShoppingCart.GetShoppingCart();
      cart.RemoveItem(productId);
      }

      // We now have to re-setup the data so that the GridView doesn’t keep
      // displaying the old data
      BindData();
      }

      protected void btnUpdateCart_Click(object sender, EventArgs e) {
      foreach (GridViewRow row in gvShoppingCart.Rows) {
      if (row.RowType == DataControlRowType.DataRow) {
      // We’ll use a try catch block in case something other than a number is typed in
      // If so, we’ll just ignore it.
      try {
      // Get the productId from the GridView’s datakeys
      int productId = Convert.ToInt32(gvShoppingCart.DataKeys[row.RowIndex].Value);
      // Find the quantity TextBox and retrieve the value
      int quantity = int.Parse(((TextBox)row.Cells[1].FindControl(“txtQuantity”)).Text);
      ShoppingCart cart = ShoppingCart.GetShoppingCart();
      cart.SetItemQuantity(productId, quantity);
      } catch (FormatException) { }
      }
      }

      BindData();
      }
      }

    • sean says:

      tanx Kris. But the ShoppingCart.cs was not posted. can only see the Default.aspx.c and ViewCart.aspx.cs files. All the vb files are complete though.

      Tanx again. I used this shopping cart example for a website without knowing the bugs in it (now it’s misbehaving big time). I will try your fix as soon as I av the complete file.

  11. Kris Crosby says:

    //Default.aspx.cs

    using System;

    public partial class _Default : System.Web.UI.Page {
    protected void Page_Load(object sender, EventArgs e) {

    }

    protected void btnAddShoes_Click(object sender, EventArgs e) {
    // Add product 1 to the shopping cart
    ShoppingCart cart = ShoppingCart.GetShoppingCart();
    cart.AddItem(1);
    // Redirect the user to view their shopping cart
    Response.Redirect(“ViewCart.aspx”);
    }

    protected void btnAddShirt_Click(object sender, EventArgs e) {
    ShoppingCart cart = ShoppingCart.GetShoppingCart();
    cart.AddItem(2);
    Response.Redirect(“ViewCart.aspx”);
    }

    protected void btnAddPants_Click(object sender, EventArgs e) {
    ShoppingCart cart = ShoppingCart.GetShoppingCart();
    cart.AddItem(3);
    Response.Redirect(“ViewCart.aspx”);
    }

    }

  12. Kris Crosby says:

    For VB, I used a C#->VB converter for the changed code for the same 3 files (ShoppingCart.vb,Default.aspx.vb and ViewCart.aspx.vb) Someone should really update the example files. A shopping cart for one person doesn’t make any sense and dispite the good intention of the author, if your going to teach something which establishes yourself as an expert, teach it right, and fix your mistakes acurately if they are discovered later. I am no programmer and I have to fix this code for all you programmers out there.

    • Kris Crosby says:

      ‘ ShoppingCart.vb
      Imports Microsoft.VisualBasic

      ‘ The ShoppingCart class
      ‘ Holds the items that are in the cart and provides methods for their manipulation
      Public Class ShoppingCart

      #Region “Properties”

      Private _items As List(Of CartItem)
      Public Property Items() As List(Of CartItem)
      Get
      Return _items
      End Get
      Private Set(ByVal value As List(Of CartItem))
      _items = value
      End Set
      End Property

      #End Region

      #Region “Implementation”

      ‘ Readonly variables can only be set in initialization or in a constructor
      Public Shared ReadOnly Instance As ShoppingCart

      Public Shared Function GetShoppingCart() As ShoppingCart
      ‘ If the cart is not in the session, create one and put it there
      If HttpContext.Current.Session(“ASPNETShoppingCart”) Is Nothing Then
      Dim cart As New ShoppingCart()
      cart.Items = New List(Of CartItem)()
      HttpContext.Current.Session(“ASPNETShoppingCart”) = cart
      End If

      Return (DirectCast(HttpContext.Current.Session(“ASPNETShoppingCart”), ShoppingCart))

      End Function

      #End Region

      #Region “Item Modification Methods”

      ‘ AddItem() – Adds an item to the shopping
      Public Sub AddItem(ByVal productId As Integer)
      ‘ Create a new item to add to the cart
      Dim newItem = New CartItem(productId)

      ‘ If this item already exists in our list of items, increase the quantity
      ‘ Otherwise, add the new item to the list
      If Items.Contains(newItem) Then
      For Each item As CartItem In Items
      If item.Equals(newItem) Then
      item.Quantity += 1
      Return
      End If
      Next
      Else
      newItem.Quantity = 1
      Items.Add(newItem)
      End If

      End Sub

      ‘ SetItemQuantity() – Changes the quantity of an item in the cart
      Public Sub SetItemQuantity(ByVal productId As Integer, ByVal quantity As Integer)
      ‘ If we are setting the quantity to 0, remove the item entirely
      If quantity = 0 Then
      RemoveItem(productId)
      Return
      End If

      ‘ Find the item and update the quantity
      Dim updatedItem = New CartItem(productId)
      For Each item As CartItem In Items
      If item.Equals(updatedItem) Then
      item.Quantity = quantity
      Return
      End If
      Next
      End Sub

      ‘ RemoveItem() – Removes an item from the shopping cart
      Public Sub RemoveItem(ByVal productId As Integer)
      Dim removedItem = New CartItem(productId)

      For Each item As CartItem In Items
      If item.Equals(removedItem) Then
      Items.Remove(item)
      Return
      End If
      Next
      End Sub

      #End Region

      #Region “Reporting Methods”

      ‘ GetSubTotal() – returns the total price of all of the items before tax, shipping, etc.
      Public Function GetSubTotal() As Decimal
      Dim subTotal As Decimal = 0
      For Each item As CartItem In Items
      subTotal += item.TotalPrice
      Next

      Return subTotal
      End Function

      #End Region

      End Class

    • Kris Crosby says:

      ‘ Default.aspx.vb
      ‘ The ShoppingCart class
      ‘ Holds the items that are in the cart and provides methods for their manipulation
      Public Class ShoppingCart

      #Region “Properties”

      Private _items As List(Of CartItem)
      Public Property Items() As List(Of CartItem)
      Get
      Return _items
      End Get
      Private Set(ByVal value As List(Of CartItem))
      _items = value
      End Set
      End Property

      #End Region

      #Region “Implementation”

      ‘ Readonly variables can only be set in initialization or in a constructor
      Public Shared ReadOnly Instance As ShoppingCart

      Public Shared Function GetShoppingCart() As ShoppingCart
      ‘ If the cart is not in the session, create one and put it there
      If HttpContext.Current.Session(“ASPNETShoppingCart”) Is Nothing Then
      Dim cart As New ShoppingCart()
      cart.Items = New List(Of CartItem)()
      HttpContext.Current.Session(“ASPNETShoppingCart”) = cart
      End If

      Return (DirectCast(HttpContext.Current.Session(“ASPNETShoppingCart”), ShoppingCart))

      End Function

      #End Region

      #Region “Item Modification Methods”

      ‘ AddItem() – Adds an item to the shopping
      Public Sub AddItem(ByVal productId As Integer)
      ‘ Create a new item to add to the cart
      Dim newItem = New CartItem(productId)

      ‘ If this item already exists in our list of items, increase the quantity
      ‘ Otherwise, add the new item to the list
      If Items.Contains(newItem) Then
      For Each item As CartItem In Items
      If item.Equals(newItem) Then
      item.Quantity += 1
      Return
      End If
      Next
      Else
      newItem.Quantity = 1
      Items.Add(newItem)
      End If

      End Sub

      ‘ SetItemQuantity() – Changes the quantity of an item in the cart
      Public Sub SetItemQuantity(ByVal productId As Integer, ByVal quantity As Integer)
      ‘ If we are setting the quantity to 0, remove the item entirely
      If quantity = 0 Then
      RemoveItem(productId)
      Return
      End If

      ‘ Find the item and update the quantity
      Dim updatedItem = New CartItem(productId)
      For Each item As CartItem In Items
      If item.Equals(updatedItem) Then
      item.Quantity = quantity
      Return
      End If
      Next
      End Sub

      ‘ RemoveItem() – Removes an item from the shopping cart
      Public Sub RemoveItem(ByVal productId As Integer)
      Dim removedItem = New CartItem(productId)

      For Each item As CartItem In Items
      If item.Equals(removedItem) Then
      Items.Remove(item)
      Return
      End If
      Next
      End Sub

      #End Region

      #Region “Reporting Methods”

      ‘ GetSubTotal() – returns the total price of all of the items before tax, shipping, etc.
      Public Function GetSubTotal() As Decimal
      Dim subTotal As Decimal = 0
      For Each item As CartItem In Items
      subTotal += item.TotalPrice
      Next

      Return subTotal
      End Function

      #End Region

      End Class

      Partial Class _Default
      Inherits System.Web.UI.Page

      Protected Sub btnAddShoes_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddShirt.Click
      ‘ Add product 1 to the shopping cart
      Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
      cart.AddItem(1)

      ‘ Redirect the user to view their shopping cart
      Response.Redirect(“ViewCart.aspx”)
      End Sub

      Protected Sub btnAddShirt_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddShorts.Click
      Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
      cart.AddItem(2)
      Response.Redirect(“ViewCart.aspx”)
      End Sub

      Protected Sub btnAddPants_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddShoes.Click
      Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
      cart.AddItem(3)
      Response.Redirect(“ViewCart.aspx”)
      End Sub
      End Class

      • Ben Streissguth says:

        Thanks to Kris for doing all of that. :) Just wanted to post the actual code for Default.aspx.vb as there seems to be a double post for the ShoppingCard class.

        Partial Class _Default
        Inherits System.Web.UI.Page

        Protected Sub btnAddShoes_Click(sender As Object, e As EventArgs)
        ‘ Add product 1 to the shopping cart
        Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
        cart.AddItem(1)
        ‘ Redirect the user to view their shopping cart
        Response.Redirect(“ViewCart.aspx”)
        End Sub

        Protected Sub btnAddShirt_Click(sender As Object, e As EventArgs)
        Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
        cart.AddItem(2)
        Response.Redirect(“ViewCart.aspx”)
        End Sub

        Protected Sub btnAddPants_Click(sender As Object, e As EventArgs)
        Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
        cart.AddItem(3)
        Response.Redirect(“ViewCart.aspx”)
        End Sub
        End Class

    • Kris Crosby says:

      ‘ ViewCart.aspx.vb

      Partial Class ViewCart
      Inherits System.Web.UI.Page

      Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      ‘ ASP.NET keeps track of the state of all server controls
      ‘ (like the GridView). Because of this, we don’t need to supply it with
      ‘ the data every time the page loads. (No more re-checking checkboxes
      ‘ that were checked or re-selecting the right item in the drop-down when
      ‘ the page Is submitted. It’s all done for you!)

      If Not IsPostBack Then
      BindData()
      End If
      End Sub

      Protected Sub BindData()
      ‘ Let’s give the data to the GridView and let it work!
      ‘ The GridView will take our cart items one by one and use the properties
      ‘ that we declared as column names (DataFields)
      Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
      gvShoppingCart.DataSource = cart.Items
      gvShoppingCart.DataBind()
      End Sub

      Protected Sub gvShoppingCart_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles gvShoppingCart.RowDataBound
      ‘ If we are binding the footer row, let’s add in our total
      If e.Row.RowType = DataControlRowType.Footer Then
      Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
      e.Row.Cells(3).Text = “Total: ” & cart.GetSubTotal().ToString(“C”)
      End If
      End Sub

      ‘ This is the method that responds to the Remove button’s click event
      Protected Sub gvShoppingCart_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs) Handles gvShoppingCart.RowCommand
      If e.CommandName = “Remove” Then
      Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
      Dim productId = Convert.ToInt32(e.CommandArgument)
      cart.RemoveItem(productId)
      End If

      ‘ We now have to re-setup the data so that the GridView doesn’t keep displaying the old data
      BindData()
      End Sub

      End Class

      • Ben Streissguth says:

        The missing bit…

        Protected Sub btnUpdateCart_Click(sender As Object, e As EventArgs)
        For Each row As GridViewRow In gvShoppingCart.Rows
        If row.RowType = DataControlRowType.DataRow Then
        ‘ We’ll use a try catch block in case something other than a number is typed in
        ‘ If so, we’ll just ignore it.
        Try
        ‘ Get the productId from the GridView’s datakeys
        Dim productId As Integer = Convert.ToInt32(gvShoppingCart.DataKeys(row.RowIndex).Value)
        ‘ Find the quantity TextBox and retrieve the value
        Dim quantity As Integer = Integer.Parse(DirectCast(row.Cells(1).FindControl(“txtQuantity”), TextBox).Text)
        Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()
        cart.SetItemQuantity(productId, quantity)
        Catch generatedExceptionName As FormatException
        End Try
        End If
        Next

        BindData()
        End Sub

  13. Yanayaya says:

    Reading over the comments are we now at a point where this code works and can allow multiple users to place orders? Also I note that this tutorial uses static values in a drop down for price and item.

    What would be the coding to gather that information from a database??

  14. Rakesh Prasad says:

    URGENT URGENT URGENT URGENT URGENT URGENT

    hi,
    This code is nice but it has big issue.
    My cart is sare to all user.I want one cart for one user not shareable cart.
    Plz help me!

    send code to amity.prasad@gmail.com

  15. BxBEnny says:

    Tnx a lot. Why did u use Session? Is it the best way to solve security problem?

  16. Dan Petru says:

    Following Kris Crosby modiffications fixes everything

  17. magic says:

    Nice and clean
    gj dude

  18. Ami Gill says:

    Nice Work…Thanks.

  19. narinder says:

    nice coding it solve my problem

  20. I downloaded the source codes and pasted them into my shell files and they worked as advertised. I guess I’m learning through reverse engineering. I really like asp.net and C#, I just wish there were tutorials available that are “beginner-friendly” and professionally presented. Sigh…….

  21. mark says:

    Hi everyone!
    Great tut! but how can i use it with sql server and import data in the gridview to the database?
    Please! help me!
    Thanks!

  22. james says:

    Great! Question, where would i change the VB code to reflect say pricing groups? (i.e. 0-5 = $3.99, etc)?

    Great demo, great coding…thanks a million!

  23. Anders says:

    How do i get product info from database?

  24. ShinVieTNAm says:

    if (HttpContext.Current.Session[ASPNETShoppingCart] == null)
    {
    Instance = new ShoppingCart();
    Instance.Items = new List();
    HttpContext.Current.Session[ASPNETShoppingCart] = Instance;
    }
    else
    {
    Instance = (ShoppingCart)HttpContext.Current.Session[ASPNETShoppingCart];
    }

    ——————————————————- u wrong
    Client A , Client B ( or IE and Firefox

    Step 1 ..
    Client A Add Product ..
    Step 2 ..
    Client B submit View Card
    step 3 .. you will see the clients product B is added to Client A
    :D
    sorry . I dont know English ..

  25. grant says:

    Has anyone managed to populate the products from the database rather than use static ones?

  26. Nitropropain says:

    it’s save my time. thx.

  27. influenceuk says:

    I would like to know if we can use a Database on this code, and how do we impliment it? I see there is a product class so i am guessing we’d need to modify that to get the data?

    Could someone please post an update to get this working with a Database please?

  28. engchun says:

    thanks for the code sample , ShoppingCart cart = ShoppingCart.GetShoppingCart(); <– this is the line that call data from product.cs file right , if i am using mysql database , please advice convert code to mysql . thanks is advance

  29. George says:

    Hello! thanks for this tutorial but I have a problem! when I click on
    Add three KWL-JFE to cart
    open cart and there is a message like this

    Warning: Invalid argument supplied for foreach() in E:\xampp\htdocs\EXPEREMENTS\new\shopping-carts\shop_net\demo\cart_action.php on line 13

    what’s a problem?

  30. Vineet says:

    Thanks Don for such a wonderful article, its really help me a lot, I was also very painful for me to remove singleton class, but i am again thankful for you regarding your solution ………….and also thanks to all other post and their author for understanding of the article

  31. Norm says:

    I am stil pretty new to ASP.NET. I would like to run this shopping cart code under .NET framework 2.0. What is the equivaent syntax for the folowing code? Please advice/

    public List Items { get; private set; }

    Changing to the following code will compile, but it will not work. You get Stackoverflow error.
    public List Items
    {
    get
    {
    return Items ;
    }

    set
    {
    Items = value;
    }
    }

  32. Norm says:

    Kris Crosby,
    Somehow, I cannot convert yoru shopping cart.vb to C#. Do you have the Shopping cart.cs
    Norm

  33. Norm says:

    It is alright. I got it all fixed now. Norm

  34. chade says:

    It’s nice untill the client clicks on his browser back/forward button:(

  35. Hi friends, need a help here

    When i tried the above example i was left with this error,

    ‘CartItem.Quantity.get’ must declare a body because it is not marked abstract or extern

    for the coing – ” public int Quantity { get; set; } ”

    I get this for all the properties that have left with empty get and set..

    Any idea what has to be done.

    Thanks in advance

  36. Marcelb says:

    Hi there, to add an MSSQL database backend to this you need to replace the code below in product.vb

    Public Sub New(ByVal id As Integer)
    Me.Id = id
    If id = 1 Then
    Me.Price = 20.95
    Me.Description = “Shoes”
    ElseIf id = 2 Then
    Me.Price = 9.95
    Me.Description = “Shirt”
    ElseIf id = 3 Then
    Me.Price = 15.95
    Me.Description = “Pants”
    End If

    with

    Public Sub New(ByVal id As Integer)

    Dim conn As SqlConnection
    Dim cmdSELECT As SqlCommand
    Dim connString As String

    connString = ConfigurationManager.ConnectionStrings(“MarcelConnectionString”).ConnectionString
    conn = New SqlConnection(connString)
    cmdSELECT = New SqlCommand()
    cmdSELECT.Connection = conn
    cmdSELECT.CommandText = “selectInvent”
    cmdSELECT.CommandType = Data.CommandType.StoredProcedure
    cmdSELECT.Parameters.Add(New SqlParameter(“@id”, id))
    conn.Open()

    Dim rdr As SqlDataReader = cmdSELECT.ExecuteReader()

    Me.Price = 0
    Me.Description = “”
    Do While (rdr.Read())

    Me.Price = rdr.GetDecimal(rdr.GetOrdinal(“value”))
    Me.Description = rdr.GetString(rdr.GetOrdinal(“title”))

    Loop

    cmdSELECT.Dispose()
    cmdSELECT = Nothing
    conn.Close()
    conn = Nothing

    The code uses a stored procedure as below:

    CREATE PROCEDURE [dbo].[selectInvent]
    – Add the parameters for the stored procedure here
    @id as integer

    AS
    BEGIN
    – SET NOCOUNT ON added to prevent extra result sets from
    – interfering with SELECT statements.
    SET NOCOUNT ON;

    — Insert statements for procedure here
    select value, title
    FROM tbl_stockinventory
    WHERE id=@id

    END

    Hope this helps people….

  37. Allan Kendall says:

    I was wondering how this solution could be adjusted to get the product information from a database. If you where to use a gridview and a sql datassource for example how would you code the back end so that the products where not hard coded into the pages.

    If you are going to make an online shop of anykind I find it hard to believe that you would hardcode stock into your pages, that just wouldnt happen. To make this better it would be nice if someone could perhaps demonstrate how we can use a database populated products gridview for stock selection.

    Anyone have any ideas?

  38. I came across your code while training a new hire. The fix is to remove the static constructor and change the Instance variable to a property. Comment out the static constructor and change the instance variable as follows:

    public static ShoppingCart Instance
    {
    get
    {
    ShoppingCart c=null;
    if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)
    {
    c = new ShoppingCart();
    c.Items = new List();
    HttpContext.Current.Session.Add(“ASPNETShoppingCart”, c);
    }
    else
    {
    c = (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];
    }
    return c;
    }
    }

  39. dongitlhu says:

    how can I use a database with this code? I have a Product table and how to show data from this table?

  40. Rakesh says:

    First of all, thanks for the helpful codes, it really help me in understanding the working of Shopping cart…
    But, I have a question….
    1. how to add Paypal or google checkout or etc for the paying the amount.
    2. How the number of products(Quantity) recorded in the database will be reduce….say I have 5 quantity of particular item in the database….After the successful checkout(buying) how it will be reduced to 4 or 3 or 2 or 0.

  41. Thomas says:

    Hi,
    does anyone figure out what needs to be changed in this tutorial to make the cart not the same for all users?
    Now everyone sees the same cart, which is a bit pointless for online shopping…

    Thomas

  42. Rob says:

    Nice cart however this isnt anything anyone can use in the real world. it would be nice if authors of articles like this could make realworld examples…if this was article would have been wired up to a database this would be one of the best articles written and for a simple and yet very good cart. also it would have gotten a whole lot more traffic than it has.

    I dont want to be a downer…so good job on this but if you trully wanna make tutorials and educate beginners give them real world examples…

    peace out,

  43. Felix åkerbäck says:

    Hey!

    Do you build it in Adobe Dreamweaver CS5? And do you build the other thing in Visual Express?

  44. KESHAV DEY says:

    Hi,
    does anyone figure out what needs to be changed in this tutorial to make the cart not the same for all users?
    Now everyone sees the same cart, which is a bit pointless for online shopping…
    Shopping cart maintain its contain even browser is closed or reopen from any other computer
    using the same ip address . How to reset the cart when it open for the first time becomes a big problem in ur example..

  45. triad1984 says:

    I don’t think anyone wants to post a database solution for this cart becuase custom shopping carts are pretty big business and if we share it here everyone will run off and create turn key solutions off this one guy’s code and I’m sure no one here has the decency to offer royalties to the author. So, since the database piece is really the meat and potatoes of an online cart I would think it’s safe to say no one’s going to provide the code.

  46. Stam says:

    Hi. Can anybody post ShiopCart.cs&? Thnx

  47. Bbaale says:

    Thank you very much,God bless your family

  48. Neoteny says:

    You have given a clear idea and specific direction for database which is going to help almost everyone. Thanks for sharing such an informative post. Nice information, many thanks to the author. It is incomprehensible to me now. You did a great job and your article is very informative.

  49. masoud says:

    tanx for information

  50. Arun says:

    How do i make it to use with different users.
    All users are having the same cart

Comment Page 2 of 3 1 2 3

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.