Ninject InRequestScope有时似乎会返回错误的实例

时间:2016-03-02 09:23:57

标签: caching dependency-injection asp.net-mvc-5 ninject requestscope

我正在开发一个使用MVC 5 application来处理依赖注入的Ninject。应用程序定义了SecurityService,它提供了有关当前登录用户的各种信息。我正在使用Windows身份验证。

好的,让我们深入了解代码。

NinjectWebCommon.cs

    private static readonly Bootstrapper bootstrapper = new Bootstrapper();
    private static KernelBase kernel;

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ISecurityService>().To<SecurityService>().InRequestScope();

        // custom bindings are defined here
    }

    public static void PerformInjectionOn(object instance)
    {
        kernel.Inject(instance);
    }

请注意安全绑定定义kernel.Bind<ISecurityService>().To<SecurityService>().InRequestScope();

SecurityService.cs

    private AppUser _CurrentUser = null;

    /// <summary>
    /// gets logged user data, based on current identity username (Sam account name)
    /// </summary>
    /// <returns>AppUser object if windows identity maps to an existing active user. Otherwise null</returns>
    public AppUser GetLoggedUserData()
    {
        lock(lockObj)
        {
            String currUsername = WindowsIdentity.GetCurrent().Name;

            // comparison between current user name and actually authenticated user is needed since some requests end with different values!
            if (_CurrentUser == null || !_CurrentUser.Username.Equals(currUsername))
            {
                _CurrentUser = _ScopedDataAccess.AppUserRepository.AllNoTracking
                    // some includes
                    .SingleOrDefault(u => u.IsEnabled && u.Username.Equals(currUsername));

                if (_CurrentUser == null)
                {
                    logger.LogEx(LogLevel.Info, "GetLoggedUserData -  user {0} authentication failed", currUsername);
                    return null;
                }
            }

            return _CurrentUser;
        }
    }

我的问题是,即使每个请求实例化SecurityService,有时我会收到_CurrentUser.UsernamecurrUsername不同的实例(即两者都是有效的A / D用户)我进行了测试。

当前的解决方法是让!_CurrentUser.Username.Equals(currUsername)使缓存的用户实例无效,如果请求身份验证的用户与缓存的用户不同,但我想知道发生了什么。

出于好奇,我检查了InThreadScope并遇到了同样的问题,但我认为这可以解释为IIS使用的线程池可能为另一个请求提供相同的线程。

有谁知道为什么InRequestScope的行为如此?

感谢。

[编辑]

当前用户与缓存的用户不同时调用堆栈:

  

ProjectName.Models.dll!ProjectName.Models.SecurityService.GetLoggedUserData()第54行C#       ProjectName.Models.dll!ProjectName.Models.SecurityService.GetAndCheckUserData()第76行C#       ProjectName.Models.dll!ProjectName.Models.SecurityService.IsAdmin.get()第98行C#       ProjectName.Models.dll!ProjectName.Models.EntitiesCache.ProjectStatuses.get()第51行C#       ProjectName.Services.dll!ProjectName.Services.ProjectService.CreateSelectorsDomain()第253行C#       ProjectName.Services.dll!ProjectName.Services.ProjectService.ProjectService(ProjectName.Models.ISecurityService securityService,ProjectName.Models.IEntitiesCache entitiesCache,ProjectName.Models.IScopedDataAccess dataAccess,ProjectName.Services.IProjectTemplateService projectTemplateService)第33行C#       [外部代码]       ProjectName.Web.dll!ProjectName.Web.NinjectWebCommon.PerformInjectionOn(对象实例)第93行C#       ProjectName.Web.dll!ProjectName.Web.BaseController.BaseController()第21行C#       [外部代码]

同步所有步骤中的逻辑(无asyncawait,无Tasks

0 个答案:

没有答案