ASP.NET Core MVC 8添加商品到购物车触发InvalidOperationException报错
ASP.NET Core MVC 8 购物车添加功能报错解决
我在ASP.NET Core MVC 8项目中实现商品添加至购物车功能,需求为:将指定商品加入购物车,若购物车条目不存在则创建并入库;重复添加同一件商品时数量加1。但操作时触发以下错误:
异常信息:CLR/System.InvalidOperationException
类型为'System.InvalidOperationException'的异常在System.Private.CoreLib.dll中抛出,未被用户代码处理:'Invalid operation. The connection is closed.'
相关代码
ShoppingCartController.cs
private readonly ILogger<ShoppingCartController> _logger; private readonly DBContext _dbContext; private const string CartSessionKey = "CartId"; private string ShoppingCartId { get; set;} public ShoppingCartController(ILogger<ShoppingCartController> logger, DBContext dBContext) { _logger = logger; _dbContext = dBContext; } public async void AddToCart(int id) { ShoppingCartId = GetCartID(); // 该行代码触发InvalidOperationException Cart cart = await _dbContext.Carts.FirstOrDefaultAsync(c => c.CartId == ShoppingCartId && c.ProductId == id); if (cart == null) { // 若购物车不存在则创建新购物车 Cart newCart = new Cart { ProductId = id, CartId = ShoppingCartId, Product = await _dbContext.Products.FirstOrDefaultAsync(p => p.ProductId == id), Count = 1, CreatedDate = DateTime.Now, }; await _dbContext.Carts.AddAsync(newCart); } else { cart.Count++; } await _dbContext.SaveChangesAsync(); } private string GetCartID() { if(HttpContext.Session.Keys.Contains(CartSessionKey) == false) { if (!string.IsNullOrWhiteSpace(HttpContext.User.Identity.Name)) { HttpContext.Session.SetString(CartSessionKey,HttpContext.User.Identity.Name); } else { Guid tempCartId = Guid.NewGuid(); HttpContext.Session.SetString(CartSessionKey, tempCartId.ToString()); } } return HttpContext.Session.GetString(CartSessionKey); }
Dashboard.cshtml
<div class="d-flex"> <div class="row rows-cols-4"> @foreach(var prod in @ViewBag.Products) { <div class="card m-1" style="width: 18rem;"> <img src="..." class="card-img-top" alt="..."> <div class="card-body"> <h5 class="card-title">@prod.ProductName</h5> <a class="btn btn-primary" asp-controller="Customer" asp-action="ProductDetails" asp-route-id="@prod.ProductId">More Details</a> <!-- 点击此按钮添加商品到购物车 --> <a class="btn btn-primary" asp-controller="ShoppingCart" asp-action="AddToCart" asp-route-id="@prod.ProductId">Add to cart</a> </div> </div> } </div> </div>
Cart.cs
public class Cart { public int Id { get; set; } public int Count { get; set; } public string CartId { get; set; } public DateTime CreatedDate { get; set; } public int ProductId { get; set; } public virtual Product Product { get; set; } }
报错原因及解决方法
1. 核心问题:使用async void作为控制器动作方法返回类型
ASP.NET Core控制器动作方法中使用async void会导致请求上下文提前释放,DbContext的数据库连接也会被关闭,进而触发"连接已关闭"的异常。必须改为返回async Task<IActionResult>:
修改AddToCart方法签名及内容:
public async Task<IActionResult> AddToCart(int id) { ShoppingCartId = GetCartID(); Cart cart = await _dbContext.Carts.FirstOrDefaultAsync(c => c.CartId == ShoppingCartId && c.ProductId == id); if (cart == null) { Cart newCart = new Cart { ProductId = id, CartId = ShoppingCartId, // 不需要手动赋值Product导航属性,EF会通过ProductId自动关联 Count = 1, CreatedDate = DateTime.Now, }; await _dbContext.Carts.AddAsync(newCart); } else { cart.Count++; } await _dbContext.SaveChangesAsync(); // 添加重定向或返回结果,比如回到商品列表页 return RedirectToAction("Dashboard", "Customer"); }
2. 移除不必要的导航属性赋值
创建Cart对象时手动查询Product并赋值是多余的,EF Core会通过ProductId自动维护导航属性,这不仅节省数据库查询,还能避免潜在的上下文问题。
3. 确认Session配置正确
确保在Program.cs中已经配置了Session服务,否则GetCartID方法无法正常工作:
builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); // 中间件配置要放在UseRouting之后,UseEndpoints之前 app.UseSession();
4. 确保DbContext生命周期配置正确
默认情况下DBContext是作用域生命周期(Scoped),这符合控制器的生命周期,不要将其注册为单例(Singleton),否则会导致连接复用问题。
内容的提问来源于stack exchange,提问作者DonDavid12
相关产品推荐
相关产品推荐

