具有标识的StructureMap DbContext

时间:2018-05-26 18:27:01

标签: c# asp.net asp.net-identity structuremap

所以我最近开始使用结构图。我有一个使用身份的web api。我的目标是每个请求都有一个dbcontext。目前我遇到了上下文问题,通过结构图注入的上下文与用户管理器使用的上下文不同。我环顾四周,无法找到解决方案,即使我确定它非常明显。

首先,我有我的结构图设置。

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);
    }

我已经减少了代码,但我有典型的服务和存储库层结构。所有使用structuremap注入,服务和存储库都有正确的上下文,唯一不在于用户管理器。我知道下面的一行引起了这个问题:

app.CreatePerOwinContext(ApplicationDbContext.Create);

然而,就像我说我仍然习惯于构造地图,我以前使用统一,只会从当前容器解析我需要的实例。非常感谢任何帮助或指导。

1 个答案:

答案 0 :(得分:1)

您对所有这些问题的疑问:

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

首先,您告诉中间件管理DbContext的创建。然后,您告诉中间件管理ApplicationUserManager的创建,ApplicationUserManager.Create获取由该中间件管理的ApplicationDbContext实例,而不是您的DI容器。同样适用于您的ApplicationRoleManager。最后,您有两种方法可以为每个请求生成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容器注入之外,除去所有其他创建这些实例的方法。

我的old blog post中的更多信息 - 滚动到&#34;清理&#34;有关中间件注册的详细信息。