.NET6站点无法将BasketItem添加到Cart Session的问题
问题描述
构建.NET6 Umbraco站点时,从HttpContext.Current.Session切换到新Session方案后,触发AddToBasket动作能创建Session和BasketItem实例,但无法将BasketItem加入Cart Session,视图中获取的Cart始终为null,导致/basket页面无法显示商品项。
关键问题与修复方案
1. Session中间件注册顺序错误
Session中间件必须在Umbraco中间件之前注册,否则Umbraco的请求处理逻辑会先执行,Session无法绑定到当前请求上下文。
修复后Configure方法:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // 先注册Session相关中间件 app.UseCookiePolicy(); app.UseSession(); app.UseUmbraco() .WithMiddleware(u => { u.UseBackOffice(); u.UseWebsite(); }) .WithEndpoints(u => { u.UseInstallerEndpoints(); u.UseBackOfficeEndpoints(); u.UseWebsiteEndpoints(); }); }
2. Cart修改后未重新持久化到Session
GetCart()从Session获取Cart实例后,调用AddProduct修改了内部集合,但修改后的Cart没有重新保存回Session,导致Session中的Cart始终是初始空状态。
修复后ProductPageAddToBasket方法:
[HttpPost] public IActionResult ProductPageAddToBasket(decimal productPrice) { if (!ModelState.IsValid) return CurrentUmbracoPage(); bool addedToCart = false; if (productPrice > 0) { var cart = GetCart(); addedToCart = cart.AddProduct(CurrentPage, 1, productPrice); // 修改后必须重新保存到Session SessionHelper.SetObjectsession(HttpContext.Session, "Cart", cart); TempData[addedToCart ? "success" : "failure"] = addedToCart ? "商品已成功加入购物车..." : "加入购物车时出错,请重试..."; } return RedirectToCurrentUmbracoPage(); }
3. SessionHelper泛型方法硬编码类型问题
原SessionHelper.GetObjectsession硬编码返回Cart类型,无法支持泛型复用,且视图中类型引用可能存在匹配问题。
修复后SessionHelper类:
public static class SessionHelper { public static void SetObjectsession(this ISession session, string key, object value) { session.SetString(key, JsonConvert.SerializeObject(value)); } public static T GetObjectsession<T>(this ISession session, string key) where T : class, new() { var value = session.GetString(key); return string.IsNullOrEmpty(value) ? new T() : JsonConvert.DeserializeObject<T>(value); } }
4. Cart私有字段无法被序列化
Cart类中的private List<BasketItem> lineCollection是私有字段,Json.NET默认不会序列化私有字段,导致Session中保存的Cart没有商品数据。
修复方案二选一:
- 方案1:将私有字段改为公共属性
public class Cart { public List<BasketItem> LineCollection { get; set; } = new List<BasketItem>(); // AddProduct方法修改为使用LineCollection public bool AddProduct(IPublishedContent productPage, int quantity, decimal price) { BasketItem line = LineCollection.FirstOrDefault(product => product.ProductPage.Id == productPage.Id); // 剩余逻辑不变 } }
- 方案2:给私有字段添加序列化特性
public class Cart { [JsonProperty] private List<BasketItem> lineCollection = new List<BasketItem>(); // 原AddProduct逻辑不变 }
5. BasketItem中复杂类型序列化问题
IPublishedContent是Umbraco的复杂类型,直接序列化会导致数据异常,建议改用商品ID存储,而非直接存储实例:
public class BasketItem { public int ProductPageId { get; set; } public int Quantity { get; set; } public decimal Price { get; set; } public bool IsOptionalExtra { get; set; } public bool IsMainProduct { get; set; } public string Description { get; set; } public int? ExtraMainProductPageId { get; set; } }
6. 视图类型引用一致性问题
确保视图中Cart类型的命名空间与后端一致,建议在视图顶部添加命名空间引用:
@using YourProjectNamespace.Models @{ var basketCart = HttpContext.Session.GetObjectsession<Cart>("Cart"); }
内容的提问来源于stack exchange,提问作者StuartP

