如何将我的Autofac容器插入ASP.NET Identity 2.1

ren*_*pez 39 asp.net asp.net-mvc owin asp.net-identity

我一直在研究新版ASP.NET Identity 2.1的新功能,其中一项增强功能是集成到OWIN中间件中的新IoC功能.我在这些例子中看到的一句话是这一句:

app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
Run Code Online (Sandbox Code Playgroud)

这句话接收一个函数委托,它返回示例中提供的管理器实现的新实例:

 public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options,
        IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>())); 
Run Code Online (Sandbox Code Playgroud)

我个人不喜欢这个实现,因为我无法使用容器为这些管理器注入任何我想要的依赖项.

还有一个"神奇地""IdentityFactoryOptions"和"IOwinContext"被"神奇地"注入到我无法进入我的IoC容器的函数中.

有没有人对此实施有更好的解决方法?

Ben*_*tle 49

我从一个开箱即用的MVC5安装开始,并使用AutoFac作为IoC容器.听起来我正在努力实现与你类似的目标,所以让我解释一下我做了什么.作为免责声明,我对使用IoC和Identity非常陌生.

我相信如果您使用自己的IOoCContext是不必要的,那么我将切换到使用AutoFac注册我的ApplicationUserManager.要做到这一点,我不得不:

从Startup.Auth中删除CreatePerOwinContext行,因为我将注册ApplicationDbContextApplicationUserManager在AutoFac中.

//app.CreatePerOwinContext(ApplicationDbContext.Create);
//app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
Run Code Online (Sandbox Code Playgroud)

修改ApplicationUserManager构造函数参数,并包含Create函数中的所有内容.

public ApplicationUserManager(IUserStore<ApplicationUser> store, IdentityFactoryOptions<ApplicationUserManager> options)
        : base(store)
{
    //all the code from the 'Create' function here, using `this` for `manager`
}
Run Code Online (Sandbox Code Playgroud)

将AccountController设置为使用一个构造函数ApplicationUserManager作为参数并废弃从中获取的UserManager属性.ApplicationUserManagerOwinContext

private ApplicationUserManager _userManager; //every thing that needs the old UserManager property references this now
public AccountController(ApplicationUserManager userManager) 
{
    _userManager = userManager;
}
Run Code Online (Sandbox Code Playgroud)

使用AutoFac注册所有内容,包括IdentityFactoryOptions实例.

var x = new ApplicationDbContext();
builder.Register<ApplicationDbContext>(c => x);
builder.Register<UserStore<ApplicationUser>>(c => new UserStore<ApplicationUser>(x)).AsImplementedInterfaces();
builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>()
{
    DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationName")
});
builder.RegisterType<ApplicationUserManager>();
Run Code Online (Sandbox Code Playgroud)

这是粗略的总结.我可能错过了其他一些我必须要做的调整.

  • 好东西,但这可能是一个更好的autofac配置builder.RegisterType <ApplicationDbContext> .AsSelf().InstancePerRequest(); builder.Register <UserStore <ApplicationUser >>()AsImplementedInterfaces()InstancePerRequest().; builder.Register <IdentityFactoryOptions <ApplicationUserManager >>(c => new IdentityFactoryOptions <ApplicationUserManager>(){DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationName")}); builder.RegisterType <ApplicationUserManager>()AsSelf()InstancePerRequest().; (15认同)
  • 我还发现这篇文章对同一主题非常有帮助:http://www.talksharp.com/configuring-autofac-to-work-with-the-aspnet-identity-framework-in-mvc-5 (2认同)
  • @angularsen这看起来像你引用的文章的当前版本:https://developingsoftware.com/configuring-autofac-to-work-with-the-aspnet-identity-framework-in-mvc-5/.TalkSharp URL返回301 Moved Permanently. (2认同)

Vla*_*scu 29

Ben的回答是正确的,但它手动实例化DbContext并在注册其余类型时使用此实例.IMO,这是一个坏主意(不应该为所有请求使用相同的永久db上下文).

Derek的评论是一个很大的改进,但它没有将数据库上下文传递给用户存储,导致诸如"实体类型ApplicationUser不是当前上下文模型的一部分"之类的错误.

我在下面提供了我的代码供参考 - 它与Derek的相似.

builder.RegisterType<MyApplicationContext>().AsSelf().InstancePerRequest()
//...

builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
builder.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerRequest();
builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<MyApplicationContext>())).AsImplementedInterfaces().InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();
builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>
{
    DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("Application?")
}); 
Run Code Online (Sandbox Code Playgroud)