【问题标题】:ASP.NET MVC Dependency Injection with UnityContainer Session State带有 UnityContainer 会话状态的 ASP.NET MVC 依赖注入
【发布时间】:2010-02-20 04:07:41
【问题描述】:

我有一个 asp.net mvc 网站,我在其中使用“Micorosoft.Practices.Unity”和“Microsoft.Practices.ObjectBuilder2”的依赖注入功能。通过将我的对象注入到我的控制器构造函数中,这一切都很好。

问题是当用户离开浏览器或想要注销时,我很难清除此会话。所有值都保留在对象中。如何销毁在 Session_End() 上的 global.asax 中创建的容器,或者通过用户单击并通过控制器操作来处理。

下面是一些示例代码。

Global.asax - 由Session_start 执行:

protected static void RegisterDependencies()
{
    IUnityContainer container = new UnityContainer();

    container.RegisterType<DataStore, DataStore>(new SessionLifetimeManager<DataStore>());
    container.RegisterType<IMotorRepository, MotorRepository>(new SessionLifetimeManager<IMotorRepository>());
    container.RegisterType<ICoverRepository, CoverRepository>(new SessionLifetimeManager<ICoverRepository>());
    container.RegisterType<IDriverRepository, DriverRepository>(new SessionLifetimeManager<IDriverRepository>());
    container.RegisterType<IVehicleRepository, VehicleRepository>(new SessionLifetimeManager<IVehicleRepository>());
    container.RegisterType<ICodeValueRepository, CodeValueRepository>(new SessionLifetimeManager<ICodeValueRepository>());

    ControllerBuilder.Current.SetControllerFactory(
        new UnityControllerFactory(container)
    );
}

SessionLifeTimeManager:

public class SessionLifetimeManager<T> : LifetimeManager, IDisposable
{
    public override object GetValue()
    {
        return HttpContext.Current.Session[typeof(T).AssemblyQualifiedName];
    }
    public override void RemoveValue()
    {
        HttpContext.Current.Session.Remove(typeof(T).AssemblyQualifiedName);
    }
    public override void SetValue(object newValue)
    {
        HttpContext.Current.Session[typeof(T).AssemblyQualifiedName] = newValue;
    }
    public void Dispose()
    {
        RemoveValue();
    }
}

【问题讨论】:

  • 也许我弄错了,但你正在做的事情看起来很可怕,就像你试图拥有每个会话容器一样。我要说的第一件事是 - 除非你有逻辑调用' SetControllerFactory' 其他地方..你应该为受伤做好准备 - 因为 SetControllerFactory 为整个应用程序设置控制器工厂..而不是会话。

标签: asp.net-mvc dependency-injection


【解决方案1】:

Session_End 直到用户离开后大约 30 分钟才会触发。我也遇到过 ASP.NET 中的会话问题。

如果您调用 Session.Abandon,您可以强制触发 Session_end。但是,如果用户离开您的网站或关闭浏览器,这并不能解决您的问题。

您可以也许使用 javascript 事件并在他们离开页面时进行网络服务调用来结束他们的会话。这类似于试图阻止用户在保存工作之前离开的逻辑。

这有什么问题吗?每次页面转换都会使会话过期。

window.onbeforeunload = endSession;

function endSession() {
    //end session here through some kind of call back to the server
}

我之前做过一个页面,但是,其中一些功能会导致弹出窗口阻止用户离开,而其他功能(如回发)不会触发该事件。我最终要做的是在页面加载时设置一个 var,然后在与某些控件或链接交互时修改该 var。

var endUserSession = true;

window.onbeforeunload = endSession;

function endSession() {
    if(endUserSession) {
        //end session here through some kind of call back to the server
    }
}

虽然这是一个非常具有侵入性的实现,并且需要大量工作和集成才能在整个站点范围内实现,但它可以工作,尽管让您的回发不触发结束会话会很耗时。

根据我的个人经验,最好让会话自行处理,而不用担心它何时到期或何时到期。我花了太多的时间来解决会话问题。 IIS 应该为您处理它,您可以进入工作进程并更改 WP 重新启动(和会话清除)的频率。

如果这里的问题与可用的系统资源有关:即站点只是占用大量内存并且转储会话不是一个选项,您可以实现 Sql Server 状态服务器,然后回收所有您想要的工作进程.

How to implement sql state server

【讨论】:

    【解决方案2】:

    第一个评论者提到的这种方法的问题是,您既要创建与会话关联的容器,又要将与该容器关联的对象的生命周期设置为会话。

    真的,您不需要两者都做。要么注册将容器与会话相关联,要么将对象的生命周期设置为会话。

    我更喜欢将对象的生命周期设置为会话,因为它可以让我的容器创建更干净。只需将您的容器创建移动到应用程序级别。当用户(即一个唯一的会话)请求一个在容器中注册的类型的对象并且该对象的生命周期是会话时,它将在该用户的会话中查找该对象。如果没有找到,它会将其添加到会话中。如果找到,它将从会话中返回。如果另一个用户出现并请求相同类型的对象,则会发生相同的模式,因为该对象的后备存储对于每个用户都是唯一的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-21
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      相关资源
      最近更新 更多