asp.net-mvc ASP.Net MVC 控制器构造函数中的会话为空

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/889516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:35:26  来源:igfitidea点击:

Session null in ASP.Net MVC Controller Constructors

asp.net-mvcsession

提问by Chris Arnold

Why is Session null in the constructors of Controllers? It can be accessed from Action methods. Presumably, because the MVC Routing framework is responsible for newing-up a Controller, it just hasn't (re-)instantiated the Session at that point.

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

Does anyone know if this is by design and, if so, why?

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

[I have managed to circumvent the problem by using a Lazy Loading Pattern.]

[我已经通过使用延迟加载模式设法规避了这个问题。]

采纳答案by Andrew W

Andrei is right - it is null because when running under the ASP.NET MVC framework, the HttpContext (and therefore HttpContext.Session) is not set when the controller class is contructed as you might expect, but it set ("injected") later by the ControllerBuilder class. If you want a better understanding of the lifecycle you can either pull down the ASP.NET MVC framework (the source is available), or refer to: this page

Andrei 是对的 - 它是空的,因为在 ASP.NET MVC 框架下运行时,HttpContext(因此 HttpContext.Session)在控制器类如您所期望的那样构造时未设置,但它稍后设置(“注入”)通过 ControllerBuilder 类。如果你想更好地理解生命周期,你可以下拉ASP.NET MVC框架(源码可用),或者参考:这个页面

If you need to access the Session then one way would be to override the "OnActionExecuting" method and access it there, as it will be available by that time.

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

However, as Andrei is suggesting, if your code is reliant on the Session then it could potentially be difficult to write unit tests, so perhaps you could consider wrapping the Session in a helper class which can then be swapped out for a different, non-web version when running under unit tests, therefore de-coupling your controller from the web.

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

回答by Mike Chamberlain

In addition to the other answers here, while Controller.Sessionis not populated in the constructor, you can still access the session through:

除了此处的其他答案外,虽然Controller.Session未在构造函数中填充,但您仍然可以通过以下方式访问会话:

System.Web.HttpContext.Current.Session

System.Web.HttpContext.Current.Session

with the standard caveat that this potentially reduces your controller's testability.

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

回答by Andrei R?nea

The Session is injected later in the life-cycle. Why do you need the session in the constructor anyway? If you need it for TDD you should wrap the session into a mockable object.

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

回答by Funlover

You can override the Initialize method to set your session.

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

protected override void Initialize(RequestContext requestContext)

回答by VahidN

If you are using an IoC Container, try injecting and using the HttpSessionStateBaseinstead of the Sessionobject:

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

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

回答by Prashanth vunnam gcs

This answer might be useful for some people

这个答案可能对某些人有用

If we override Initialize method then we have to initialize base class with request context : base.Initialize(requestContext);

如果我们重写 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"]);
            }

        }