使用UnityContainer会话状态的ASP.NET MVC依赖注入

时间:2009-06-11 18:35:50

标签: asp.net-mvc dependency-injection

我有一个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();
    }
}

2 个答案:

答案 0 :(得分:0)

在用户离开后30分钟之前,不会触发Session_End。我也遇到了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 State Server,然后回收所有您想要的工作进程

How to implement sql state server

答案 1 :(得分:0)

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

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

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