StructureMap DbContext с идентичностью - PullRequest
0 голосов
/ 26 мая 2018

Так что я недавно начал использовать карту структуры.У меня есть веб-API с использованием идентичности.Моя цель - иметь dbcontext для каждого запроса.В настоящее время у меня возникают проблемы с контекстом, контекст, введенный через структурную карту, отличается от того, который используется менеджером пользователей.Я оглянулся и не могу найти решение, хотя я уверен, что оно довольно очевидно.

Итак, для начала у меня есть мои настройки Structuremap.

public class DefaultRegistry : Registry {
    #region Constructors and Destructors

    public DefaultRegistry() {
        Scan(
            scan => {
                scan.TheCallingAssembly();
                scan.AddAllTypesOf<IImporterService>().NameBy(type => type.Name);
                scan.WithDefaultConventions();
            });

        For<IHttpContextBaseWrapper>().Use<HttpContextBaseWrapper>();
        For<ApplicationDbContext>().Use(() => new ApplicationDbContext());
        For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current));
    }

    #endregion
}

Мне не нужно вводить менеджер пользователя на данный момент, поскольку к нему обращаются через httpcontext в базовой службе, я знаю, что это, вероятно, придется изменить для модульного тестирования в будущем.

Далее у нас есть авторизация при запуске.

private void ConfigureOAuthTokenGeneration(IAppBuilder app)
    {
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

        //Token Auth
        var OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/api/account/login"),
            Provider = new ApplicationOAuthProvider("self"),
            AuthorizeEndpointPath = new PathString("/api/AccountApi/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(121),
            RefreshTokenProvider = new ApplicationRefreshTokenProvider(),
            //#if DEBUG
            AllowInsecureHttp = true,
            //#endif
        };

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);
    }

Я сократил код, но у меня типичная структура уровней обслуживания и хранилища.Все инъекции с использованием структуры карты, службы и репозиториев имеют правильный контекст, единственным, на который не распространяется диспетчер пользователей.Я знаю, что строка ниже вызывает проблему:

app.CreatePerOwinContext(ApplicationDbContext.Create);

Однако, как я уже говорил, я все еще привыкаю к ​​структуре карты, я ранее использовал Unity и просто разрешил нужный мне экземпляр из текущего контейнера.Любая помощь или руководство очень ценится.

1 Ответ

0 голосов
/ 27 мая 2018

Ваша проблема со всеми этими строками:

    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

Сначала вы указываете промежуточное ПО для управления созданием вашего DbContext.Затем вы указываете промежуточному программному обеспечению управлять созданием вашего ApplicationUserManager, а ApplicationUserManager.Create берет экземпляр ApplicationDbContext, управляемый этим промежуточным ПО, а не вашим контейнером DI.То же самое происходит с вашим ApplicationRoleManager.В конце у вас есть 2 способа получения ApplicationDbContext за запрос - один через ваш DI-контейнер, другой через промежуточное ПО.

Если вы хотите иметь только один экземпляр ApplicationDbContext, вам нужно избавиться от второго способа создания его экземпляра: ApplicationDbContext.Create.Это решит вашу проблему.

Однако вашему промежуточному ПО все еще необходим доступ к вашему ApplicationUserManager.Таким образом, вместо всех этих:

   app.CreatePerOwinContext(ApplicationDbContext.Create);
   app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
   app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

вам нужно использовать app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());

и избавиться от всех других способов создания этих экземпляров, кроме внедрения из вашего контейнера DI.

Дополнительная информация в моем старом сообщении в блоге - перейдите к части "Очистить" для получения подробной информации о регистрации промежуточного программного обеспечения.

...