ASP.Net MVC控制器构造函数中的会话为null

Chr*_*old 84 asp.net-mvc session

为什么Session在控制器的构造函数中为null?它可以从Action方法访问.据推测,因为MVC路由框架负责新建一个Controller,所以它当时没有(重新)实例化Session.

有谁知道这是否是设计的,如果是的话,为什么?

[我已设法通过使用延迟加载模式来解决问题.]

小智 74

Andrei是对的 - 它是null的,因为当在ASP.NET MVC框架下运行时,HttpContext(以及因此HttpContext.Session)在控制器类被构造时没有设置,如你所料,但它稍后设置("注入")由ControllerBuilder类.如果您想更好地了解生命周期,可以下拉ASP.NET MVC框架(源代码可用),或参考:此页面

如果你需要访问Session,那么一种方法是覆盖"OnActionExecuting"方法并在那里访问它,因为它将在那时可用.

但是,正如Andrei所建议的那样,如果你的代码依赖于Session,那么编写单元测试可能会很困难,所以也许你可以考虑将Session包装在一个helper类中,然后可以将它换成另一个,而不是在单元测试下运行时的Web版本,因此将控制器与Web分离.

  • 我不确定这是关于HttpContext的正确陈述.它实际上是在整个流程开始时构建的.您可以在http://www.beletsky.net/2011/06/inside-aspnet-mvc-route-to-mvchanlder.html上阅读有关详细流程的内容,或者您​​可以使用反射器并在实例化httpContext时找到自己 - 它位于httpruntime.cs的1556行左右. (2认同)

Mik*_*ain 59

除了这里的其他答案,虽然Controller.Session没有在构造函数中填充,您仍然可以通过以下方式访问会话:

System.Web.HttpContext.Current.Session

标准警告,这可能会降低控制器的可测试性.

  • 这两个会话属性中的每一个的类型都不同,如果您打算保持对会话状态本身的引用,这可能很重要. (3认同)
  • 老答案,但想说“System.Web.HttpContext.Current.Session”在 VS2019 MVC 实例中也是“null”。 (2认同)

And*_*nea 10

会话在生命周期的后期注入.为什么你还需要构造函数中的会话?如果你需要它用于TDD,你应该将会话包装成一个可模拟的对象.

  • 我想在构造函数中访问Session,以便我可以访问以前存储的会话信息.是的,我可以覆盖OnActionExecuting方法,但这肯定不是一个优雅的解决方案. (4认同)

小智 8

您可以覆盖Initialize方法来设置会话.

protected override void Initialize(RequestContext requestContext)
Run Code Online (Sandbox Code Playgroud)