2
votes

I am trying to figure out how I can change up an order by the customer over a web browser. The customer will order an item with product Id (key), the name of product, the price of the product, and the quantity he wants. I would like to know how I can change his order by replacing the OLD item with the old quantity with the same item with a different quanitity SO basically clicking to choose the item and placing 2 different quantities he wishes to purchase. The shopping cart holds the Items that are purchased, so I was wondering how I could destroy an OrderItem from the shopping cart then recreate it.

When my code find the key that is already in the shopping cart, then It needs to be destroyed and recreated with a new Quanitity (a text box from the web app).

  protected void btnOrder_Click(object sender, EventArgs e)
{
    //Check for Shoppingcart object
    // Create first if not there
    if (Session["cart"] == null)
        Session["cart"] = new ShoppingCart();
    int quantity = 0;

    // make sure there is text
    if (txtQuantity.Text.Trim().Length != 0)
    {
        quantity = int.Parse(txtQuantity.Text);

        if (((ShoppingCart)Session["cart"]).
            keyExists(int.Parse(productID.Text)))
        {
        //Here I should Destroy the current item that exists and replace with new one

        }
        else  // This is a new item
        {
            // Make the item
            OrderItem item = new OrderItem(
                int.Parse(productID.Text), productName.Text,
                double.Parse(productPrice.Text),
                int.Parse(txtQuantity.Text));
            // add to cart  
            ((ShoppingCart)Session["cart"]).addToCart(item);

        }
        // How does this work? Who is sender?
        this.btnReturn_Click(sender, e);
    }
    else
    {
        Response.Write("Nothing Ordered<br>You must order some of the product or return to the Catalog");
    }

Here is the OrderItem object

public class OrderItem
{
private int productID;
private string prodName;
private double unitPrice;
private int quantityOrdered;

private string exceptionStr;


public OrderItem(int id, string name, double price, int quantity)
{
    prodName = name;
    exceptionStr = "Numeric data must not be negative";
    if ( id < 0 || price < 0 || quantity < 0)
    {
        throw new System.ArgumentException(exceptionStr);
    }
    else
    {
        productID = id;
        unitPrice = price;
        quantityOrdered = quantity;
    }
}


#region Public Properties
public int ProductID
{
    get
    {
        return productID;
    }
}

public string ProductName
{
    get 
    {
        return prodName;
    }
}


public double UnitPrice
{
    get
    {
        return unitPrice;
    }
}


public int QuantityOrdered
{
    get
    {
        return quantityOrdered;
    }
    set
    {
        if( value < 0 )
        {
            throw new ArgumentException(exceptionStr);
        }
        else
        {
            quantityOrdered = value;
        }
    }
}

#endregion
}

Here is the Shoppingcart for your viewing:

 public class ShoppingCart : IEnumerable
 {
private SortedList theCart;

public ShoppingCart() {
    theCart = new SortedList();
} // end of Constructor


public bool HasItems {
    get{
        bool hasItems = false;
        if( theCart.Count > 0 )
            hasItems = true;
        return hasItems;
    }
    set {
        // ignore this is read only
    }
} // end of HasItems


public void addToCart(OrderItem item) {
    theCart.Add(item.ProductID, item);
}// AddToCaArt

/// <summary>
/// deletes item that is passed
/// </summary>
/// <param name="item"></param>
public void deleteFromCart(OrderItem item)
{
    theCart.Remove(item.ProductID);
} // end deleteFromCart

/// <summary>
/// deletes the item with this id key
/// </summary>
/// <param name="id"></param>
public void deleteFromCart(int id)
{
    theCart.Remove(id);
} // end deleteFromCart
public OrderItem[] getCartContents()
{

// need to create stuff
    OrderItem[] stuff = null;
    theCart.Values.CopyTo(stuff, 0);

    return (stuff);
} // end getCartContents


public bool keyExists(int ID) {

    return theCart.ContainsKey(ID);
}// end keyExists

public ICollection Values
{
    get
    {
        return theCart.Values;
    }
}

#region IEnumerable Members

public IEnumerator GetEnumerator()
{
    return theCart.GetEnumerator();
}

#endregion
}
4
What type of collection is stored in ShoppingCart (which addToCart adds to)?keyboardP
Can you post OrderItem and ShoppingCart type code?Adil
They are SortedLists, addToCart adds the productID and the item the customer choose to the SortedList name theCart, and the code for ShoppingCart and OrderItem is up.GivenPie
You can not change a variable of an object which is stored in session unless you destory and store again.Prasad Kanaparthi
Besides, when you are done with solution, try posting your code to codereview.stackexchange.com... it appears to me that there are many improvements required in design and code style.Adil

4 Answers

1
votes

In your ShoppingCart class, you could add a method called IncreaseQuantity(int productID) (and a DecreaseQuantity method).

public void IncreaseQuantity(int productID)
{
   int indexOfProduct = theCart.IndexOfKey(productID);

   if(indexOfProduct != -1)
   {
       this.theCart[indexOfProduct].quantityOrdered++;
   }
}

Then call the method from your session

ShoppingCart cart = (ShoppingCart)Session["cart"];

if (cart.keyExists(int.Parse(productID.Text)))
{
    //can store the parsed int in a variable instead to prevent...
    //having to parse twice.
    cart.IncreaseQuantity(int.Parse(productID.Text));    
}
1
votes

I would highly recommend thinking about from a class or model level how a shopping cart would look. I think a set of classes like the following would help a great deal (not the best but an ok design from scratch):

[Serializable]
public class ShoppingCartItem
{
  public ShoppingCartItem(guid key, decimal price, int quantity)
  {
    this.Key = key;
    this.Price = price;
    this.Quantity = quantity;
  }

  public Guid Key { get; private set; }
  public Decimal Price { get; private set; }
  public int Quantity { get; set; }
}

[Serializable]
public class ShoppingCart
{
  public ShoppingCart()
  {
    this.Clear();
  }

  public ICollection<ShoppingCartItem> Items { get; private set; }

  public int ItemCount 
  {
    get { return this.Items.Sum(i => i.Quantity); }
  }

  public decimal Subtotal
  {
    get { return this.Items.Sum(i => i.Quantity * i.Price); }
  }

  public void Clear()
  {
    this.Items = new List<ShoppingCartItem>();
  }
}

Now the ShoppingCart is serializable for the ability to be stored in ASP.Net session (or making a wish list :))

Now I'm not a fan of the loosely typed ASP.Net session so I borrowed, from some where I can't remember, this fantastic class to make strongly typed Session objects:

using System;
using System.Web;

namespace Company.Product.Web.UI.Domain
{
    public abstract class SessionBase<T> where T : class, new()
    {
        private static readonly Object _padlock = new Object();

        private static string Key
        {
            get { return typeof(SessionBase<T>).FullName; }
        }

        public static T Current
        {
            get
            {
                var instance = HttpContext.Current.Session[Key] as T;

                if (instance == null)
                {
                    lock (SessionBase<T>._padlock)
                    {
                        if (instance == null)
                        {
                            HttpContext.Current.Session[Key] = 
                              instance = new T();
                        }
                    }
                }

                return instance;
            }
        }

        public static void Clear()
        {
            var instance = HttpContext.Current.Session[Key] as T;
            if (instance != null)
            {
                lock (SessionBase<T>._padlock)
                {
                    HttpContext.Current.Session[Key] = null;
                }
            }
        }

    }
}

To use it for this example I would then create:

public class ShoppingCartSession : SessionBase<ShoppingCart> { }

Then I can use it anywhere in my code:

var item = ShoppingCartSession.Current.Items.FirstOrDefault(i => i.Key= key);

if (item == null)
{
  ShoppingCartSession.Current.Items.Add(
    new ShoppingCartItem(Key, price, quantity));
}
else
{
  item.Quantity = item.Quantity + quantity;
}

Strongly typed session shopping cart object that is extensible and allows you to do what you'd want and more. It can also be accessed by other parts of your application to show the number of items in the cart and a subtotal for an area, say at the top of your application to show a small preview of the shopping cart status.

0
votes

I think there is no way.

What is it that is bothering you with needing to recreate the object?
Is it performance, or keeping the code clean?

If it is a performance issue:
Consider saving a separate object on the Session for each item, like so -

int itemID = int.Parse(productID.Text);
int productQuantity = Session["item_number_" + itemID];

If it a an issue of keeping your code clean:
Consider putting all the Session logic in a property:

public ShoppingCart SessionCart
{
    get
    {
        if (Session["cart"] == null)
            return new ShoppingCart();
        else
            return (ShoppingCart)Session["cart"];
    }
    set
    {
        Session["cart"] = value;
    }
}
0
votes

Well one way is to maintain quantity as part of every OrderItem and then perhaps get the total count of shopping car by enumerating each individual OrderItem quantity. But then each OrderItem ID must be present only once ShoppingCart.

For example, add a method in ShoppingCart like

    public OrderItem Retrieve(int id)
    {
        return theCart[id] as OrderItem;
    }

And then if cart contains same product id already

    OrderItem orderItem = cart.Retrieve(1);
    item.QuantityOrdered += 1;

Finally assign the updated cart object to Session variable.

Another way to achieve is adding another OrderItem in ShoppingCart and maintaining count grouped by OrderItem Id