【发布时间】:2009-05-20 18:34:08
【问题描述】:
为什么Controllers的构造函数中Session为null?可以从 Action 方法访问它。据推测,因为 MVC 路由框架负责更新控制器,所以它当时还没有(重新)实例化 Session。
有谁知道这是否是设计使然,如果是,为什么?
[我已经设法通过使用延迟加载模式来规避这个问题。]
【问题讨论】:
标签: asp.net-mvc session
为什么Controllers的构造函数中Session为null?可以从 Action 方法访问它。据推测,因为 MVC 路由框架负责更新控制器,所以它当时还没有(重新)实例化 Session。
有谁知道这是否是设计使然,如果是,为什么?
[我已经设法通过使用延迟加载模式来规避这个问题。]
【问题讨论】:
标签: asp.net-mvc session
Andrei 是对的 - 它为 null,因为在 ASP.NET MVC 框架下运行时,在构造控制器类时未设置 HttpContext(以及因此 HttpContext.Session),但它设置了(“注入") 稍后由 ControllerBuilder 类调用。如果你想更好地理解生命周期可以拉下 ASP.NET MVC 框架(有源码),或者参考:this page
如果您需要访问 Session,那么一种方法是覆盖“OnActionExecuting”方法并在那里访问它,因为届时它将可用。
但是,正如 Andrei 所建议的,如果您的代码依赖于 Session,那么编写单元测试可能会很困难,因此也许您可以考虑将 Session 包装在一个帮助类中,然后可以将其换成不同的,在单元测试下运行时的非网络版本,因此将您的控制器与网络解耦。
【讨论】:
除了这里的其他答案,虽然Controller.Session没有填充到构造函数中,你仍然可以通过以下方式访问会话:
System.Web.HttpContext.Current.Session
标准警告是,这可能会降低控制器的可测试性。
【讨论】:
System.Web.HttpContext.Current.Session在VS2019 MVC实例中也是null。
Session 在生命周期的后期注入。为什么你仍然需要构造函数中的会话?如果 TDD 需要它,则应将会话包装到可模拟对象中。
【讨论】:
您可以覆盖 Initialize 方法来设置您的会话。
protected override void Initialize(RequestContext requestContext)
【讨论】:
如果您使用的是 IoC 容器,请尝试注入并使用 HttpSessionStateBase 而不是 Session 对象:
private static Container defaultContainer()
{
return new Container(ioc =>
{
// session manager setup
ioc.For<HttpSessionStateBase>()
.Use(ctx => new HttpSessionStateWrapper(HttpContext.Current.Session));
});
}
【讨论】:
这个答案可能对某些人有用
如果我们重写 Initialize 方法,那么我们必须使用请求上下文初始化基类:base.Initialize(requestContext);
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
}
【讨论】:
protected override void Initialize(System.Web.Routing.RequestContext requestContext).