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

ASP.NET Core过滤器向Action传对象及购物车为空问题排查

排查ASP.NET Core购物车Session过滤器中OnActionExecuted购物车对象为空的问题

让我们一步步拆解你遇到的问题,帮你定位原因并解决:

1. 先看核心矛盾:过滤器私有字段_mand为什么会空?

你的过滤器在OnActionExecuting中给_mand赋值,但到了OnActionExecuted就变成空,大概率和过滤器生命周期或对象关联逻辑有关,我们逐个排查:


原因1:过滤器被注册为单例,实例复用导致并发问题

如果你的WinkelmandSessionFilter是按Singleton(单例)注册的,多个请求会共享同一个过滤器实例。当请求并发时,可能出现某个请求的OnActionExecuted在另一个请求的OnActionExecuting之前执行,这时候_mand还没被赋值,自然是空的。

解决方法:
把过滤器注册为Scoped,确保每个请求都有独立的过滤器实例:

// 在Program.cs/Startup.cs中注册
builder.Services.AddScoped<WinkelmandSessionFilter>();

原因2:Action参数名称不匹配,模型绑定创建了新对象

你在过滤器里把购物车存入ActionArguments["cart"],但你的Action方法参数是Winkelmand mand——ASP.NET Core的模型绑定会自动创建一个新的Winkelmand实例,完全不会用到过滤器传入的cart对象。这就导致:

  • Action里修改的是全新的mand,过滤器的_mand还是原来的旧对象
  • 极端情况下,如果模型绑定失败,还可能间接导致_mand赋值流程中断

解决方法:
要么把Action参数名改成cart,让模型绑定复用过滤器传入的对象:

[ServiceFilter(typeof(WinkelmandSessionFilter))]
public IActionResult BonEdit(Winkelmand cart, NieuwViewModel model)
{
    var bon = new Bon();
    // ... 你的业务代码
    cart.bonToevoegen(bon); // 这里用cart代替原来的mand
    bon.genereerPdf();
    return RedirectToAction(nameof(BonVoorbeeld), bon);
}

要么修改过滤器里的ActionArguments键名,和参数名mand保持一致:

public override void OnActionExecuting(ActionExecutingContext context)
{
    _mand = ReadCartFromSession(context.HttpContext);
    context.ActionArguments["mand"] = _mand; // 键名和参数名统一
    base.OnActionExecuting(context);
}

原因3:Winkelmand类序列化/反序列化失败

如果Winkelmand无法被Json.NET正确序列化/反序列化,ReadCartFromSession会抛出异常,导致OnActionExecuting没完成_mand的赋值,到OnActionExecuted时_mand自然是空的。

检查点:

  • Winkelmand必须有无参构造函数(Json.NET默认要求)
  • 需要序列化的属性必须是公共的,或者配置了Json.NET可访问私有成员
  • 类中不能有循环引用(如果有,给循环引用的属性加[JsonIgnore])

验证方法:
给ReadCartFromSession加异常捕获,看看是不是序列化出了问题:

private Winkelmand ReadCartFromSession(HttpContext context)
{
    try
    {
        var cartJson = context.Session.GetString("cart");
        return string.IsNullOrEmpty(cartJson) ? new Winkelmand() : 
            JsonConvert.DeserializeObject<Winkelmand>(cartJson);
    }
    catch (Exception ex)
    {
        // 这里可以打日志,查看序列化失败的具体原因
        return new Winkelmand();
    }
}

原因4:Session根本没启用

如果你的应用没正确配置Session,调用context.Session会直接抛出异常,导致OnActionExecuting中断,_mand没机会被赋值。

检查点:
确保在Program.cs中正确配置了Session,且UseSession()的位置正确:

// 注册Session服务
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// ...

// 启用Session,必须放在UseRouting和UseEndpoints之间
app.UseSession();
app.UseRouting();
// ...
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });

额外优化建议

为了彻底避免依赖过滤器私有字段的问题,你可以直接在OnActionExecuted中从Action参数获取修改后的购物车:

public override void OnActionExecuted(ActionExecutedContext context)
{
    // 从Action参数里拿修改后的购物车
    if (context.ActionArguments.TryGetValue("mand", out var cartObj) && cartObj is Winkelmand cart)
    {
        WriteCartToSession(cart, context.HttpContext);
    }
    base.OnActionExecuted(context);
}

这样不管过滤器的私有字段状态如何,都能正确拿到最新的购物车对象。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:17:15