AutoFac与ASP.Identity

时间:2014-06-19 06:42:34

标签: asp.net asp.net-web-api autofac asp.net-identity

我使用AutoFac 3.5与WebApi Integration 3.3和Asp.Identity 2.0.1。问题是当我将 MyDbContext 指定为 InstancePerRequest 时,Asp.Net Identity存在问题。然后我得到了这种错误消息:

没有标记匹配的范围' AutofacWebRequest'从请求实例的范围中可见。这通常表示SingleInstance()组件(或类似场景)正在请求注册为每HTTP请求的组件。在Web集成下,始终从DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime请求依赖项,从不从容器本身请求。

我正在注册Asp Token提供商,如下所示:

public partial class Startup
{
    static Startup()
    {
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/token"),
            RefreshTokenProvider = (IAuthenticationTokenProvider)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IAuthenticationTokenProvider)),
            Provider = (IOAuthAuthorizationServerProvider)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IOAuthAuthorizationServerProvider)),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
            AllowInsecureHttp = true
        };
    }

    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseOAuthBearerTokens(OAuthOptions);
    }
}

AutoFac部分看起来像这样:

builder.RegisterType<MyDbContext>().As<DbContext>().InstancePerRequest();
builder.RegisterType<SimpleRefreshToken>().As<IAuthenticationTokenProvider>();
builder.Register(x => new ApplicationOAuthProvider(
                        "self",
                        x.Resolve<Func<UserManager<User>>>()).As<IOAuthAuthorizationServerProvider>();

有没有人解决过这个问题?我找到了这篇旧帖子ASP.net Identity, IoC and sharing DbContext

修改

此博客文章也有一个凌乱的解决方法http://blogs.msdn.com/b/webdev/archive/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net-identity.aspx

1 个答案:

答案 0 :(得分:4)

我能够通过从OwinContext内部获取AutofacWebRequest并解析UserManager来解决问题。

将IOwinContext传递给每个OwinMiddleware的Invoke方法。内部您可以找到Enviroment属性,它是包含大量信息的IDictionary,包括&#34; autofac:OwinLifetimeScope&#34;。 你可以得到这个LifetimeScope,它应该被标记为&#34; AutofacWebRequest&#34;因为它是为每个http请求创建的嵌套范围,并解析了您需要的对象类型。

我的实现看起来与此类似。注意我在UserManagerFactory中生成UserManager类的方式。

public class Startup
{
    static Startup()
    {
        PublicClientId = "self";

        UserManagerFactory = () =>
        {
            //get current Http request Context
            var owinContext = HttpContext.Current.Request.GetOwinContext();

            //get OwinLifetimeScope, in this case will be "AutofacWebRequest"
            var requestScope = owinContext.Environment.ContainsKey("autofac:OwinLifetimeScope");

            if (!owinContext.Environment.Any(a => a.Key == "autofac:OwinLifetimeScope" && a.Value != null))
                throw new Exception("RequestScope cannot be null...");

            Autofac.Core.Lifetime.LifetimeScope scope = owinContext.Environment.FirstOrDefault(f => f.Key == "autofac:OwinLifetimeScope").Value as Autofac.Core.Lifetime.LifetimeScope;

            return scope.GetService(typeof(UserManager<Models.UserModel>)) as UserManager<Models.UserModel>;

        };

        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProviderCustom(PublicClientId, UserManagerFactory),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        };
    }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static Func<UserManager<Models.UserModel>> UserManagerFactory { get; set; }

    public static string PublicClientId { get; private set; }

    public void Configuration(IAppBuilder app)
    {

        var builder = new ContainerBuilder();

        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        builder.RegisterType<UserModelsConvert>().InstancePerApiRequest();
        builder.RegisterType<UserStoreCustom>().As<IUserStore<Models.UserModel>>().InstancePerApiRequest();
        builder.RegisterType<UserManager<Models.UserModel>>().InstancePerApiRequest();

        //loading other projects
        builder.RegisterModule(new LogicModule());

        var container = builder.Build();

        app.UseAutofacMiddleware(container);

        //// Create the depenedency resolver.
        var resolver = new AutofacWebApiDependencyResolver(container);

        // Configure Web API with the dependency resolver
        GlobalConfiguration.Configuration.DependencyResolver = resolver;

        app.UseOAuthBearerTokens(OAuthOptions);

        //extend lifetime scope to Web API
        app.UseAutofacWebApi(GlobalConfiguration.Configuration);

        //app.UseWebApi(config);

    }
}

我希望这可以提供帮助。如果错过了什么让我知道。