用户注销时MVC Unity重置DI

时间:2014-02-18 16:11:33

标签: asp.net-mvc-4 dependency-injection unity-container

我使用unity作为我的IoC,当应用程序加载时,我在我的登录屏幕需要的global.asax中设置我的初始DI。

当用户登录时,然后设置我的主DI,为应用程序的其余部分创建所有DI内容。我正在创建的对象之一是从登录屏幕存储用户详细信息,我正在使用该dto注入我的服务以用于授权。

我遇到的问题是用户退出时的问题。我需要处理包含用户详细信息的dto。

无论如何将一个对象置于一个未在global.asax中调用的统一内?

修改

在我从global.asax调用的bootstrapper类中。此时我只需要为安全设置DI。

Dim container As IUnityContainer = Bootstrapper.UnityContainer

        SecurityContainer.RegisterContainer(container)
        MiscContainer.RegisterMiscContainer(container)

        DependencyResolver.SetResolver(New UnityDependencyResolver(container))

        ' Setup controller factory.
        ControllerBuilder.Current.SetControllerFactory(New UnityControllerFactory(container))

在我的RegisterContainer课程中,他们只有简单的注册,如下所示。

container.RegisterType(Of ILeadService, LeadService)(New ContainerControlledLifetimeManager())

在控制器中的登录post方法中,我有以下代码。这将转到安全服务以验证用户。如果他们经过身份验证,那么我需要设置DI的下一部分,这是应用程序的其余部分。我必须在这里设置此DI而不是global.asax的原因是因为我需要在所有其他服务中使用securityDto。

Public Function LogOnWindow(loginViewModel As LoginViewModel) As ActionResult

        Dim action As ActionResult = Nothing

        ' Authorise the user.
        Dim securityResponse As ISecurityResponse = Me._securityService.AuthenticateUser(loginViewModel.UserName,
                                                                                         loginViewModel.Password)

        ' Check the response is successful.
        If (securityResponse.IsSuccessful) Then

            ' Set the application id.
            securityResponse.SecurityDto.CurrentDealerApplicationId = Me._applicationType

            ' Setup the bootstrapper with the security credentials.
            Bootstrapper.InitialiseAfterLogin(securityResponse.SecurityDto)

            ' Redirect to the main application.
            action = Me.RedirectToAction("KiaDashGrid",
                                         "Kia",
                                         New With {.Language = "en-gb"})

        Else

            ' Create an error message.
            loginViewModel.MessageManager.Merge(securityResponse.MessageManager.GetMessageCollection())

        End If

        If (action Is Nothing) Then
            action = Me.View(loginViewModel)
        End If

        Return action

    End Function

securityResponse.SecurityDto包含我注入其余应用程序服务的用户凭据。

使用dto的服务构造函数示例。

Public Class LeadService
    Inherits ServiceBase
    Implements ILeadService

    Public Sub New(mapper As IMapper,
                   uow As IUnitOfWork,
                   leadRepository As ILeadRepository,
                   securityDTO As ISecurityDTO)
        MyBase.New(securityDTO)
        Me._mapper = mapper
        Me._uow = uow
        Me._leadRepository = leadRepository
        Me._fetchStrategy = New FetchStrategy(Of Lead)()

    End Sub
End Class

我希望在用户退出时重置此dto。

以下是我的注销操作方法中的代码。

<HttpGet()> _
    Public Function LogOut() As ActionResult

        ' Need to clear the security dto credentials here.            

        Return Me.RedirectToAction("LogOnWindow",
                                   "KiaLogin",
                                    New With {.Language = "en-gb"})
    End Function

我希望这些信息更有帮助。

编辑 - 2014年2月19日

我创建了自己的PerSessionLifetimeManager类,但是当我将两个用户登录到应用程序时,总是使用第二个用户gui密钥。

在我的bootstrapper课程中,我尝试了以下方法,但到目前为止都没有。

Dim manager As New PerSessionLifetimeManager()
        manager.SetValue(securityDto)
        container.RegisterType(Of ISecurityDTO, SecurityDTO)(manager)

container.RegisterInstance(securityDto, New PerSessionLifetimeManager())

下面的PerSessionLifetimeManager类。

Public Class PerSessionLifetimeManager
    Inherits LifetimeManager

    Private ReadOnly _key As Guid = Guid.NewGuid()

    Public Sub New()
        MyBase.New()
    End Sub

    Public Overrides Function GetValue() As Object
        Return HttpContext.Current.Session(Me._key.ToString())
    End Function

    Public Overrides Sub RemoveValue()
        HttpContext.Current.Session.Remove(Me._key.ToString())
    End Sub

    Public Overrides Sub SetValue(newValue As Object)
        HttpContext.Current.Session(Me._key.ToString()) = newValue
    End Sub

End Class

1 个答案:

答案 0 :(得分:1)

经过长时间的讨论后发现你使用了错误的终身经理ContainerControlledLifetimeManager

相反,您需要一个存储数据的管理器,以便它能够存活多个请求。会话容器执行此操作,SessionLifetimeMananager就像这样:

MVC3, Unity Framework and Per Session Lifetime Manager Issue

您无需取消注册任何内容,因为会话容器由应用程序服务器维护并自动终止。