管理每个会话,并要求AutoFac寿命范围在asp.net MVC 3 [英] Managing AutoFac lifetime scopes per session and request in asp.net mvc 3

查看:141
本文介绍了管理每个会话,并要求AutoFac寿命范围在asp.net MVC 3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在一个Web应用程序使用AutoFac。我有根容器,每节子容器和每个请求的子容器。我试图找出/ A最好的办法就是管理这些生命周期范围是什么。在Global.asax.cs中我已经加入以下内容:

 保护无效的Application_Start(对象发件人,EventArgs的发送)
{
    变种容器= ...;
}保护无效在session_start(对象发件人,EventArgs的发送)
{
    VAR sessionScope = container.BeginLifetimeScope(会议);    会话[Autofac_LifetimeScope] = sessionScope;
}保护无效的Application_BeginRequest(对象发件人,EventArgs的发送)
{
    VAR sessionScope =(ILifetimeScope)会议[Autofac_LifetimeScope];
    VAR requestScope = sessionScope.BeginLifetimeScope(HTT prequest);    HttpContext.Current.Items [Autofac_LifetimeScope] = requestScope;
}保护无效Application_EndRequest(对象发件人,EventArgs的发送)
{
    VAR requestScope =(ILifetimeScope)HttpContext.Current.Items [Autofac_LifetimeScope];
    requestScope.Dispose();
}保护无效Session_End中(对象发件人,EventArgs的发送)
{
    VAR sessionScope =(ILifetimeScope)会议[Autofac_LifetimeScope];    sessionScope.Dispose();
}保护无效Application_End(对象发件人,EventArgs的发送)
{
    container.Dispose();
}


  1. 我怎么能告诉AutoFac使用我requestScope为出发点越来越依赖关系,因此,我注册为InstancePerLifetimeScope的实现将得到解决使用我的requestScope?


  2. 如果这是不可能的,我能得到AutoFac创建其每个请求的生命周期范围从我sessionScope的?


  3. 还是我在错误的轨道在这里?莫不是让AutoFac意识到这个层次的其他方式?


任何帮助或其他意见的AP preciated。


在回应史蒂芬。

我仍然在原型设计的早期阶段,但有可能的事情,你可以有在sessionScope:


  • 用户preferences

  • 验证和授权方面(例如用户身份和角色)

不关我要构建应用程序,但在电子商务环境下,购物车可能是会话范围。这可能是最好的具体例子。这是你期望寿命比要求的东西,但短于应用程序。

有可能会比这更多,但如果我有用户preferences,认证和授权的策略,则该策略也被应用到稍后将创建的其他组件。

一个可能的选择是在请求开始获得所有必要的信息,并在请求范围内将这些配置的组件。它将给我结果,我期望,但它并没有对应用程序 - >会话级>层次的要求我的模型在我的脑海匹配。我希望创建一个系统,这是有道理的,因为我绝对不会说是要维护它的人。


解决方案

什么你需要做的是实现自己的 Autofac.Integration.Mvc.ILifetimeScopeProvider 。这个接口是什么支配如何/在哪里获取生成请求生命周期范围。默认的, Autofac.Integration.Mvc.RequestLifetimeScopeProvider ,处理对每个请求的基础上创建,处理和寿命范围的维修。

<一个href=\"https://$c$c.google.com/p/autofac/source/browse/src/Source/Autofac.Integration.Mvc/RequestLifetimeScopeProvider.cs?r=78fc513a3336369c6a5acf298daa1510d051716d\">You可以浏览code为 RequestLifetimeScopeProvider 这里,我强烈建议做的,如果你打算在此进行。这是我能想到的工作包含code显示出这些东西的责任的最好样本。

您实施 ILifetimeScopeProvider 的将是你抢会话子容器,产卵从请求容器,并在请求结束,清理请求容器。你也可以在那里建立会话的容器,如果它不存在。处理清理/处置会话容器可能是在那里棘手,但是从设计的角度来看,它会是不错的,如果这一切都在一个地方,而不是一些供应商,一些在你的应用程序类。

一旦你有你的 ILifetimeScopeProvider 当你设置你的依赖解析器,你会使用它。

  VAR scopeProvider =新MyCustomLifetimeScopeProvider(集装箱,configAction);
VAR解析器=新AutofacDependencyResolver(集装箱,scopeProvider);
DependencyResolver.SetResolver(旋);

一对夫妇的警告有关的会话级范围的概念的话:


  1. 您的内存占用量可能是巨大的。您打算为您的系统上的每个用户一生范围告终。虽然请求生命周期弹出并迅速消失pretty,这些会话级范围将生活可能很长一段时间。如果你有很多的会话范围的项目,你将不得不为每个用户pretty好户型的内存使用情况。如果人们没有适当退出抛弃自己的会议,这是所有这些东西越长寿。

  2. 寿命范围及其内容不能序列化。 <一href=\"https://$c$c.google.com/p/autofac/source/browse/src/Source/Autofac/Core/Lifetime/LifetimeScope.cs\">Looking在code代表LifetimeScope ,它没有标记 [Serializable接口] ...即使它是,生活在那里的解决对象不一定所有标记序列化。这一点很重要,因为这意味着你的会话级一辈子范围可能与内存中会话单箱工作,但如果部署到与SQL会话或会话服务的一个农场,事情就会土崩瓦解,因为会议无法序列存储的范围。如果您选择不序列化的范围,那么你有跨机器每个用户不同的范围 - 也是一个潜在的问题

  3. 会话并不总是水化。如果被访问的处理程序(例如,web表单)不执行<一href=\"http://msdn.microsoft.com/en-us/library/system.web.sessionstate.irequiressessionstate\">IRequiresSessionState,会议将不会被水化(无论是在进程内或没有)。 Web表单和 MvcHandler 实现,默认情况下,所以你不会发现任何问题,但如果你有需要注射自定义处理程序,因为会话不会对这些请求存在,您会打一些障碍。

  4. Session_End中并不总是火。 <一href=\"http://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstatemodule.end.aspx\">Per在SessionStateModule.End 的文档,如果你使用外进程内会话状态,你不会真正得到Session_End中的事件,所以你将无法收拾。

由于限制,它总体上是好的,试图远离会话存储示波器的路程。但是...如果这就是你要去做的事,在 ILifetimeScopeProvider 是做它的方式。

I want to use AutoFac in a web application. I have the root container, a child container per session and a child container per request. I'm trying to figure out what the/a best way is to manage these lifetime scopes. In the Global.asax.cs I have added the following:

protected void Application_Start(object sender, EventArgs e)
{
    var container = ...;
}

protected void Session_Start(object sender, EventArgs e)
{
    var sessionScope = container.BeginLifetimeScope("session");

    Session["Autofac_LifetimeScope"] = sessionScope;
}

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var sessionScope = (ILifetimeScope) Session["Autofac_LifetimeScope"];
    var requestScope = sessionScope.BeginLifetimeScope("httpRequest");

    HttpContext.Current.Items["Autofac_LifetimeScope"] = requestScope;
}

protected void Application_EndRequest(object sender, EventArgs e)
{
    var requestScope = (ILifetimeScope)HttpContext.Current.Items["Autofac_LifetimeScope"];
    requestScope.Dispose();
}

protected void Session_End(object sender, EventArgs e)
{
    var sessionScope = (ILifetimeScope)Session["Autofac_LifetimeScope"];

    sessionScope.Dispose();
}

protected void Application_End(object sender, EventArgs e)
{
    container.Dispose();
}

  1. How can I tell AutoFac to use my requestScope as the starting point for getting dependencies, so that the implementations I register as InstancePerLifetimeScope will be resolved using my requestScope?

  2. If that is not possible, can I get AutoFac to create its per-request lifetime scope out of my sessionScope?

  3. Or am I on the wrong track here? Could there be an other way of making AutoFac aware of this hierarchy?

Any help or other comments are appreciated.


In response to Steven.

I'm still in the early stages of prototyping, but possible things you could have in the sessionScope:

  • UserPreferences
  • Authentication and authorization context (e.g. user identity and roles)

Not related to the application I'm going to build, but in a e-commerce environment, the shopping cart could be session scoped. This is probably the best concrete example. It is something that you expect to live longer than a request, but shorter than the application.

There could be more than this, but if I have a strategy for the UserPreferences, Authentication and Authorization, then that strategy could also be applied to other components that will be created later.

A possible alternative is to get all the necessary information at the beginning of the request and place these configured components in the request scope. It will give me the result I expect, but it doesn't match the model I have in my mind about application->session->request hierarchy. I'm hoping to create a system that makes sense, since I'm definitely not the one that is going to maintain it.

解决方案

What you'll need to do is implement your own Autofac.Integration.Mvc.ILifetimeScopeProvider. This interface is what governs how/where request lifetime scopes get generated. The default one, Autofac.Integration.Mvc.RequestLifetimeScopeProvider, handles creation, disposal, and maintenance of lifetime scopes on a per-request basis.

You can browse the code for RequestLifetimeScopeProvider here, which I highly recommend doing if you plan on undertaking this. It's the best sample I can think of containing working code showing the responsibility of one of these things.

Your implementation of ILifetimeScopeProvider will be where you grab the session child container, spawn the request container from that, and, at the end of the request, clean up the request container. You may also want to create the session container in there if it doesn't exist. Handling cleanup/disposal of the session container may be tricky in there, but from a design perspective, it'd be nice if it was all in one place rather than some in the provider, some in your application class.

Once you have your ILifetimeScopeProvider you'll use it when you set up your dependency resolver.

var scopeProvider = new MyCustomLifetimeScopeProvider(container, configAction);
var resolver = new AutofacDependencyResolver(container, scopeProvider);
DependencyResolver.SetResolver(resolver);

A couple of words of warning about the notion of a session-level scope:

  1. Your memory footprint could be huge. You're going to end up with a lifetime scope for every user on your system. While a request lifetime pops up and goes away pretty quickly, these session-level scopes will live potentially a long time. If you have a lot of session-scoped items, you're going to have a pretty good sized memory usage for each user. If people "abandon" their sessions without properly logging out, that's all the longer these things will live.
  2. Lifetime scopes and their contents aren't serializable. Looking at the code for LifetimeScope, it's not marked [Serializable]... and even if it was, the resolved objects living in there are not necessarily all marked serializable. This is important because it means your session-level lifetime scope might work on a single box with in-memory session, but if you deploy to a farm with SQL session or a session service, things will fall apart because the session can't serialize your stored scope. If you choose not to serialize the scope, then you have a different scope for each user across machines - also a potential problem.
  3. Session isn't always rehydrated. If the handler being accessed (e.g., the web form) doesn't implement IRequiresSessionState, the session won't be rehydrated (whether it's in-proc or not). Web forms and the MvcHandler implement that by default so you won't see any issues, but if you have custom handlers that require injection you'll hit some snags since "Session" won't exist for those requests.
  4. Session_End doesn't always fire. Per the docs on SessionStateModule.End, if you use out-of-proc session state you won't actually get the Session_End event, so you won't be able to clean up.

Given the restrictions, it's generally good to try to stay away from session-stored scopes. However... if that's what you're going to do, the ILifetimeScopeProvider is the way to do it.

这篇关于管理每个会话,并要求AutoFac寿命范围在asp.net MVC 3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆