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

时间:2009-05-20 18:34:09

标签: asp.net-mvc session

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

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

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

6 个答案:

答案 0 :(得分:72)

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

如果您需要访问Session,那么一种方法是覆盖“OnActionExecuting”方法并在那里访问它,因为到那时它将可用。

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

答案 1 :(得分:55)

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

System.Web.HttpContext.Current.Session

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

答案 2 :(得分:10)

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

答案 3 :(得分:7)

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

protected override void Initialize(RequestContext requestContext)

答案 4 :(得分:2)

如果您使用的是IoC容器,请尝试注入并使用HttpSessionStateBase而不是Session对象:

private static Container defaultContainer()
{
    return new Container(ioc =>
    {
        // session manager setup
        ioc.For<HttpSessionStateBase>()
           .Use(ctx => new HttpSessionStateWrapper(HttpContext.Current.Session)); 
    });
}

答案 5 :(得分:0)

此答案可能对某些人有用

如果我们重写Initialize方法,则必须使用请求上下文初始化基类:base.Initialize(requestContext);

protected override void Initialize(RequestContext requestContext)
        {
            base.Initialize(requestContext);
            if (web == null && Session != null && Session["APPLIANCE_URL"] != null)
            {
                web = new WebServices((String)Session["APPLIANCE_URL"]);
            }

        }