You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击HTML元素执行代码不跳转刷新,EF Core实现购物车商品添加至数据库

Hey there! Let's tackle this no-refresh add-to-cart feature you're building. The core problem with your current approach is that returning a view from your HttpPost action forces a full page reload. Instead, we need to use asynchronous requests (AJAX) to send data to the backend, handle the EF Core database update, and return JSON to update the UI without reloading. Here's a step-by-step solution:

1. Frontend: Send Async Request with AJAX

We'll use vanilla JavaScript to bind a click event to your add-to-cart icons, send a POST request to the backend without reloading the page, and update the UI once we get a response.

First, make sure your add-to-cart icon/button includes a data attribute for the product ID:

<button class="add-to-cart-btn" data-product-id="123">🛒 Add to Cart</button>

Then add this script to your view (or a separate JS file):

// Bind click event to all add-to-cart buttons
document.querySelectorAll('.add-to-cart-btn').forEach(btn => {
    btn.addEventListener('click', async (e) => {
        e.preventDefault(); // Stop default page navigation/reload
        const productId = btn.dataset.productId;
        const csrfToken = document.querySelector('input[name="__RequestVerificationToken"]').value;

        try {
            const response = await fetch('/Cart/AddToCart', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'RequestVerificationToken': csrfToken // Critical for CSRF protection
                },
                body: JSON.stringify({ productId: parseInt(productId) })
            });

            if (response.ok) {
                const result = await response.json();
                // Update cart UI (e.g., update the item count in your cart icon)
                document.querySelector('.cart-item-count').textContent = result.cartCount;
                alert('Product added to cart successfully!');
            } else {
                alert('Failed to add product. Please try again later.');
            }
        } catch (error) {
            console.error('Request error:', error);
            alert('Network error. Please check your connection.');
        }
    });
});

Note: Ensure your page includes the ASP.NET Core anti-forgery token (usually added via @Html.AntiForgeryToken() in your layout or view) to prevent CSRF attacks.

2. Backend: Create a JSON-returning API Action

Instead of returning a view, your HttpPost action will return a JsonResult with success status and cart metadata. This lets the frontend know the result without reloading.

First, define a simple request model to accept the product ID:

public class AddToCartRequest
{
    public int ProductId { get; set; }
}

Then implement the action in your CartController:

private readonly AppDbContext _context;
private readonly IHttpContextAccessor _httpContextAccessor;

// Inject your DbContext and HttpContextAccessor via constructor
public CartController(AppDbContext context, IHttpContextAccessor httpContextAccessor)
{
    _context = context;
    _httpContextAccessor = httpContextAccessor;
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddToCart([FromBody] AddToCartRequest model)
{
    if (!ModelState.IsValid)
    {
        return Json(new { success = false, message = "Invalid product ID" });
    }

    // Handle authenticated vs anonymous users
    string cartIdentifier;
    if (User.Identity.IsAuthenticated)
    {
        cartIdentifier = User.FindFirstValue(ClaimTypes.NameIdentifier); // Use user ID
    }
    else
    {
        // Generate a unique ID for anonymous users and store in session
        cartIdentifier = _httpContextAccessor.HttpContext.Session.GetString("AnonymousCartId");
        if (string.IsNullOrEmpty(cartIdentifier))
        {
            cartIdentifier = Guid.NewGuid().ToString();
            _httpContextAccessor.HttpContext.Session.SetString("AnonymousCartId", cartIdentifier);
        }
    }

    // Update cart with EF Core
    var existingCartItem = await _context.CartItems
        .FirstOrDefaultAsync(ci => ci.CartIdentifier == cartIdentifier && ci.ProductId == model.ProductId);

    if (existingCartItem != null)
    {
        // Item already exists: increment quantity
        existingCartItem.Quantity += 1;
    }
    else
    {
        // New item: add to cart
        var newCartItem = new CartItem
        {
            CartIdentifier = cartIdentifier,
            ProductId = model.ProductId,
            Quantity = 1,
            CreatedAt = DateTime.UtcNow
        };
        _context.CartItems.Add(newCartItem);
    }

    await _context.SaveChangesAsync();

    // Calculate total cart items to return to frontend
    var totalCartItems = await _context.CartItems
        .Where(ci => ci.CartIdentifier == cartIdentifier)
        .SumAsync(ci => ci.Quantity);

    return Json(new { success = true, cartCount = totalCartItems });
}

Note: Replace AppDbContext and CartItem with your actual DbContext and cart entity class. The CartItem should include fields like CartIdentifier (for user/anonymous cart), ProductId, Quantity, and CreatedAt.

3. Key Things to Keep in Mind
  • CSRF Protection: Never skip including the anti-forgery token in your AJAX request—this prevents malicious attacks.
  • Anonymous User Handling: Storing a unique cart ID in session ensures unauthenticated users can still add items to their cart. You can later merge this cart with the user's account when they log in.
  • UI Feedback: Always update the frontend (like the cart item count) after a successful request—users need visual confirmation that their action worked.
  • Error Handling: Both frontend and backend should handle failures gracefully (e.g., invalid product IDs, database errors) and provide clear messages to the user.

内容的提问来源于stack exchange,提问作者Twenty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:29:39