Question Background:
I have a shopping cart system that allows people to update the amount of each item in the cart. This is made through an AJAX POST request from the ViewCartContents.cshtml
View to a method on my controller called UpdateAllCartItems
. All Items are kept in a list in a session variable called 'Cart'.
The Issue:
If a user adds a single item to their cart(i.e 1 unit) then decides to update the amount to 5 then the cart item object stored in the session list has its cart quantity property updated from 1 to 5. The issue comes when a users clicks to another page then clicks the back button to the cart and the cart quantity amount is back to 1 and not 5. I can confirm that if I refresh the page then the amount is correct so the session is being correctly updated, it just seems the view data is incorrect.
The following pcitures show the issue
1) The user adds an item to the cart:
2) The user updates the item quantity to 5, the cart total is also updated to the price of 5 items:
3) The user clicks onto a different page on the site, then clicks the back button to go back to the cart. The item quantity has returned to 1 and the total is also only showing the price of 1 item, obviously this is incorrect.
The Code:
AJAX Post request:
$(".updateCart").click(function () {
$("tr.item").each(function () {
var $prodId = $(this).find("td.prodId").html();
var $prodQty = $(this).find("input").val();
$.ajax({
url: '@Url.Action("UpdateAllCartItems")',
type: 'POST',
data: {
"id": $prodId,
"qty": $prodQty
},
success: function (updatedCart) {
document.getElementById("CartList").innerHTML = "";
for (var i = 0; i < updatedCart.cartItems.length; i++) {
AddItemsToCartDropDown(updatedCart.cartItems[i].CartItemName, updatedCart.cartItems[i].CartItemQty, updatedCart.cartItems[i].CartItemPrice);
}
var html = '<span class="pull-left glyphicon glyphicon glyphicon-shopping-cart" id="CartItemsTotal"></span> <b>' + updatedCart.cartItems.length + '</b> item(s) <strong class="caret glyphicon glyphicon-triangle-bottom"></strong>';
$('#totalCartPrice').html('<h3>Total: £' + updatedCart.cartPrice + '</h3>');
document.getElementById("CartDropdownHolder").innerHTML = html;
}
});
});
});
The UpdateAllCartItems method on the Cart Controller:
public ActionResult UpdateAllCartItems(string id, string qty)
{
CartItems = (List<CartItem>)Session["Cart"];
foreach (var item in CartItems)
{
if (item.CartItemId == Convert.ToInt32(id))
{
item.CartItemQty = qty;
}
}
CartItems = (List<CartItem>)Session["Cart"];
string cartTotal = CalculateCartTotal(CartItems);
Session["Cart"] = CartItems;
return Json(new {cartItems = CartItems, cartPrice = cartTotal });
}
If anyone could give me an idea on how to go about solving this frustrating issue that would be much appreciated.
At any time, when you press the back button in the browser, the browser loads the cached page. So the page you are seeing with only 1 quantity is the cached page. You are changing the quantity in the client side using javascript and it will not be cached by the browser.
This can be overcome by using OutputCache Attribute for the MVC Action that loads the page.
Generally OutputCache Attribute is used to improve the performance by caching the page in the browser. It can also be used to control the cache that is done by the browser. Add the OutputCache Attribute with the below properties and the page will not be cached by the browser and every time you click back button in the browser, it will send a new request to the server to fetch the page with latest information.
[OutputCache(Duration=0, VaryByParam="none", Location=OutputCacheLocation.Client, NoStore=true)]
public ActionResult Cart()
{
//your code goes here.
}
Hope this helps.
Thanks, R. Venkatesan