Search code examples
c#asp.net-mvcasp.net-core

ASP.NET MVC Cart quantity update and remove item from cart


I'm new so please don't be hard with me.

I create Cart and try to update the quantity of items inside the view, also to remove the item. But nothing works. Please help me guys.

These are my view models, services, controller and view:

public class CartItemViewModel
{
    public int Id { get; set; }
    public int ProductId { get; set; }
    public string ProductName { get; set; } = string.Empty;
    public string ProductImageUrl { get; set; } = string.Empty;

    [Required(ErrorMessage = RequireErrorMessage)]
    [Range(OrderItemQuantityMinValue,OrderItemQuantityMaxValue,
        ErrorMessage = QuantityErrorMessage)]
    public int Quantity { get; set; }
    public decimal ProductPrice { get; set; }
    public decimal TotalPrice { get; set; }
    public int CartId { get; set; } 
}
public class CartViewModel
{
    public int Id { get; set; }
    public string UserId { get; set; } = null!;
    public decimal GrandTotal { get; set; }
    public IEnumerable<CartItemViewModel> CartItems { get; set; } = new List<CartItemViewModel>();
}
public async Task<bool> RemoveCartItemFromCartAsync(int cartItemId)
{
     var cartItem = await context.CartsItems.FindAsync(cartItemId);

     if (cartItem != null)
     {
         context.CartsItems.Remove(cartItem);
         await context.SaveChangesAsync();
         return true;
     }

     return false;
}

public async Task<bool> UpdateCartItemQuantityAsync(int cartItemId, int newQuantity)
{
     var cartItem = await context.CartsItems.FindAsync(cartItemId);

     if (cartItem != null)
     {
         cartItem.Quantity = newQuantity;
         await context.SaveChangesAsync();
         return true;
     }

     return false;
}
[HttpPost]
public async Task<IActionResult> RemoveFromCart(int cartItemId)
{
    try
    {
        var result = await cartService.RemoveCartItemFromCartAsync(cartItemId);

        if (!result)
        {
            return NotFound();
        }
        
        return RedirectToAction(nameof(Cart));
    }
    catch (Exception)
    {
        return BadRequest();
    }
}

[HttpPost]
public async Task<IActionResult> UpdateCartItemQuantity(int cartItemId, int newQuantity)
{
    if (newQuantity <= 0)
    {
        return BadRequest("Invalid quantity.");
    }

    try
    {
        var result = await cartService.UpdateCartItemQuantityAsync(cartItemId, newQuantity);

        if (!result)
        {
            return NotFound();
        }

        return RedirectToAction(nameof(Cart));
    }
    catch (Exception )
    {
        return BadRequest();
    }
}
@model CartViewModel

<div class="row">
    <div class="col-12">
        <h1>Your Cart</h1>

        @if (Model.CartItems.Any())
        {
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>Image</th>
                        <th>Name</th>
                        <th>Quantity</th>
                        <th>Price</th>
                        <th>Total</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in Model.CartItems)
                    {
                        <tr>
                            <td>
                                <img src="@item.ProductImageUrl" alt="Product Image" width="100px" height="100px" />
                            </td>
                            <td>@item.ProductName</td>
                            <td>
                                <form asp-controller="Cart" asp-action="UpdateCartItemQuantity" method="post">
                                    <input type="hidden" name="cartItemId" value="@item.Id" />
                                    <input type="number" name="newQuantity" value="@item.Quantity" min="1" />
                                    <button type="submit">Update</button>
                                </form>
                            </td>
                            <td>[email protected]</td>
                            <td>[email protected]</td>
                            <td>
                                <form asp-controller="Cart" asp-action="RemoveFromCart" method="post">
                                    <input type="hidden" name="cartItemId" value="@item.Id" />
                                    <button type="submit">Remove</button>
                                </form>
                            </td>
                        </tr>
                    }
                </tbody>
            </table>

            <div class="text-right">
                <h3>Total Amount</h3>
                <h3>Grand Total: [email protected]</h3>
                <a asp-action="Checkout" asp-controller="Order" class="btn btn-info">Proceed To Checkout</a>
            </div>
        }
        else
        {
            <p>Your cart is empty.</p>
        }
    </div>
</div>

I just want to make this thing works and continue with placing an order


Solution

  • I create Cart and try to update the quantity of items inside the view, also to remove the item. But nothing works

    Well, based on your shared code, I have investigated the issue and checked the details.

    I found that, your code seems correct and working as expected. Other than, your DbContext code which you haven't been included, other shared code, I checked working as expected.

    Let's consider the following sample data which I initially seeded at the database.

    enter image description here

    I have used or update and remove controller and service code and its working accordingly.

    In addition, I would like to suggest you, have you checked if the the update method has been executed while you are hitting update?

    Does that controller get hit? Also check if your get method pulling the updated items accordingly. Becuase once you have udpated the existing items, soon you should pull the latest or updated values.

    Here is the demo I have tried:

    DbContext:

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
    
        }
    
        public DbSet<ApplicationUser> ApplicationUser { get; set; }
        public DbSet<CartItemViewModel> CartsItems { get; set; }
    
    }
    

    Note: In paste bin I have cheked your OnModelCreating(ModelBuilder builder) configuration, I am not sure what's the point of your CartItem configuration, I haven't used that still working accordingly. If you exactly not sure why you have defined those, you could comment that for the time being and test, I think here is the issue.

    Model:

    Same as yours

    Controller:

    For pulling the items from database I have following as following:

    public async Task<IActionResult>  Index()
    {
        var cartItems = await _cartService.GetCartItemsAsync();
    
        return View(cartItems);
    }
    

    Service:

    public async Task<CartViewModel> GetCartItemsAsync()
    {
        
    
        var getCartIems = await _context.CartsItems.ToListAsync();
        if (getCartIems.Count == 0)
        {
            await AddCartItemsIntoTable();
            getCartIems = await _context.CartsItems.ToListAsync();
        }
    
        var myCart = new CartViewModel();
        myCart.Id = 1;
        myCart.UserId = "New User";
        myCart.GrandTotal = 1050;
        myCart.CartItems = getCartIems;
    
        return myCart;
    }
    

    View:

    Same as your and Remove, Update controller same as yours as well.

    Output:

    enter image description here

    enter image description here

    Note: Regarding, 400 its a authentication issue, please check your permission, token or userId if there's any security layer. But apart from 400 which considered as access issue, other code you've written correctly. I would suggest your to check, other stuff, like databse connection string, DbContext configuration or anything else other than your code.