Иногда кажется, что Ninject InRequestScope возвращает неправильный экземпляр

Я разрабатываю 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.Username отличается от currUsername (т.е. оба являются действительными пользователями 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.Mecls.dll!ProjectName.min.Service.Models.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 entityCache, ProjectName.Models.IScopedDataAccess dataAccess, ProjectName.Services.IProjectTemplateService, имя_проекта..Web.NinjectWebCommon.PerformInjectionOn(экземпляр объекта) Строка 93 C# ProjectName.Web.dll!ProjectName.Web.BaseController.BaseController() Строка 21 C# [Внешний код]

Логика на всех шагах синхронная (нет async, awaitнет Tasks)

0 ответов

Другие вопросы по тегам