Modifying Cart Item Remove Functionality

8 years ago
Hello Friends

What I am trying to achieve is the following functionality, where by if a user clicks the red remove button next to an item, the cart is updated, and the item is removed.

I have a fresh install of NopCom 2.10, and ready to start experimenting. I have made the following change to the [ UpdateCart ] Action inside the  [ ShoppingCartControllers ].

[ValidateInput(false)]
[HttpPost, ActionName("Cart")]
[FormValueRequired("updatecart")]
public ActionResult UpdateCart(FormCollection form, int prdId)
{
    var cart = _workContext.CurrentCustomer.ShoppingCartItems.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList();

    foreach (var sci in cart)
    {
        bool remove = (prdId == sci.Id) ? true : false;
        if (remove)
                    _shoppingCartService.DeleteShoppingCartItem(sci, true);
        else
        {
            int newQuantity = sci.Quantity;
            foreach (string formKey in form.AllKeys)
                        if (formKey.Equals(string.Format("itemquantity{0}", sci.Id), StringComparison.InvariantCultureIgnoreCase))
                        {
                            int.TryParse(form[formKey], out newQuantity);
                            break;
                        }
                    _shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer,
                        sci.Id, newQuantity, true);
       }
   }

   //updated cart
   cart = _workContext.CurrentCustomer.ShoppingCartItems.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList();
   var model = PrepareShoppingCartModel(new ShoppingCartModel(), cart, true);
   return View(model);
}


As you can see, the Action now accepts two parameters, one is the Cart Form, and the other is the ID of the product to be removed. So, now I have two questions:

1) Is my approach correct ? or are there better, simpler ways ?
2) If my approach is correct, how would I go further in this ? cause right now I don't know how to submit the form, whilst also passing in the ID of the product item to be removed.

As always, any help would be greatly appreciated.

Thank You.
8 years ago
Ciwan, Good Attempt!

I would do something slightly different though. I would create a new action all together and have the "x" call the new action. Something like this


public ActionResult RemoveShoppingCartItem(int shoppingCartItemId){
    _shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer, shoppingCartItemId, 0, false);
    return RedirectToAction("Cart");
}
8 years ago
Oh it would be perfect, please can you share it while it will be ok?
Many thanks!
8 years ago
lol Sky when I compare my attempt with yours, mine looks crap :) It seems I have over-complicated things by a wide margin.

I have gone ahead and did as you suggested, but I get the following error. I believe the error says .. it can not find a parameter of type Int32 that is necessary for the Action in the controller ! but how can that be, when I have in fact supplied an Int32 to the action via the URL !

Here's my newly added action (exactly same as yours basically).


public ActionResult RemoveItem(int prdId)
{
    _shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer, prdId, 0, false);
    return RedirectToAction("Cart");
}


When you suggest the code above, was it the whole thing ? or did you just give me a hint, and there's more that I need to do ? I ask because when I hover over [ .UpdateShoppingCartItem ] the IntelliSense doesn't give me an overloads !

Any help would be great.

Thank You.
8 years ago
The code required in ShoppingCartController


        public ActionResult RemoveFromCart(int shoppingCartItemId) {
            _shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer, shoppingCartItemId, 0, true);

            return RedirectToAction("Cart");
        }


The code required in Nop.Web.Infrastructure.RouteProvider

//shopping cart (two routes already exist for shopping carts add this one near those).

            routes.MapRoute("RemoveProductFromCart", "cart/removeitem/{shoppingCartItemId}", new {Controller = "ShoppingCart", action = "RemoveFromCart"}, new[] {"Nop.Web.Controllers"});


The code required to render a correct url in OrderSummary.cshtml


@Url.RouteUrl("RemoveProductFromCart", new { shoppingCartItemId = item.Id })


You have to make sure that you pass the shopping cart item id and not product/product variant id. Also I know there is remove from cart functionality already built in to the update cart action, but it is a personal preference of mine to split those kinds of things into separate actions.

I haven't tested the code I provided so there will probably be some modification required, but I believe it is 90% there to complete your task.
8 years ago
Works beautifully. Thank you ever so much Sky.
8 years ago
Don't forget to ensure that an updated/deleted shopping cart item belongs to a current customer.
8 years ago
a.m. wrote:
Don't forget to ensure that an updated/deleted shopping cart item belongs to a current customer.


I didn't even think about this. Can you describe the scenario where the current user would be viewing another persons shopping cart? Is this where the user impersonation comes in? Also what would be the best way for ensuring the user and cart are related?
8 years ago
There's no need to view another persons shopping cart. You can just open URLs like http://www.yourStore.com/cart/removeitem/{shoppingCartItemId} and replace {shoppingCartItemId} with any possible value. In this case you can remove shopping cart item of another person.

UPDATE: Sorry, there's no need to add additional validation to RemoveFromCart method. All required validation is already done in _shoppingCartService.UpdateShoppingCartItem. If you open this method, you'll see the following code
var shoppingCartItem = customer.ShoppingCartItems.Where(sci => sci.Id == shoppingCartItemId).FirstOrDefault();
.
8 years ago
Would I be beaten with the "anti-MVC" stick to suggest this?

(OrderSummary.cshtml   -  on the checkbox, just add jquery onclick to click the updatecart button)

<input id="removefromcart" type="checkbox" name="removefromcart" value="@(item.Id)"  onclick="$('#updatecart').click();"/>

(EDIT:  I haven't tried your method - what would happen if the customer changed a qty on another line, and then clicked the remove button on a different line?  I'd think he'd lose his qty change.)