如何将我的Autofac容器插入到ASP中。 NET身份2.1

我一直在研究ASP.NET Identity 2.1新版本的新function,其中一个增强function是集成到OWIN中间件中的新IoCfunction。 我在例子中看到的一个句子是这样的:

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

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

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

我个人不喜欢这个实现,因为我不能使用容器来为这些pipe理者注入任何依赖。

另外还有一个“IdentityFactoryOptions”和一个“IOwinContext”,它们被“神奇地”注入到了Im不能够拉入我的IoC容器的函数中。

有没有人有这个实施更好的解决方法?

我从一个开箱即用的MVC5安装开始,并使用AutoFac作为IoC容器。 这听起来像我正在努力实现与你类似的目标,所以让我解释我做了什么。 作为一个免责声明,我是相当新的使用IoC和身份。

我相信,如果您正在使用自己的IoC,IOwinContext在作为IoC的angular色中是不必要的 – 我切换到使用AutoFac注册ApplicationUserManager。 要做到这一点,我不得不:

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

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

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

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

将AccountController设置为具有以ApplicationUserManager作为参数的单个构造函数,并废除从OwinContext ApplicationUserManagerUserManager属性。

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

使用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>(); 

这是粗略的总结。 我可能错过了一些我不得不一路做的其他调整。

Ben的答案得到了一般的想法,但它手动实例化DbContext并在注册其余types时使用此实例。 海事组织,这是一个坏主意(不应该使用相同的永久数据库上下文的所有请求)。

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

我已经在下面列出了我的代码,供参考 – 它和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​") }); 

以下是您可以使用Unity将所有东西连接起来的参考资料:

 var container = new UnityContainer(); container.RegisterType<MyDbContext>(new InjectionConstructor("ConnectionStringName")); container.RegisterType<IAuthenticationManager>( new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication)); container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>( new InjectionConstructor(typeof(MyDbContext))); container.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>( new InjectionConstructor(typeof(MyDbContext))); container.RegisterType<IdentityFactoryOptions<ApplicationUserManager>>(new InjectionFactory(x => new IdentityFactoryOptions<ApplicationUserManager> { DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationName") })); container.RegisterType<ApplicationSignInManager>(); DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 

我通过使用autofac服务定位器来pipe理解决方法:

 app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>()); 

是的,这不够好,但同时,我们可以使用与autofac注册过程中声明的对象相同的范围。

现在详细介绍Autofac Docs上的MVC5 Owin集成 :

  • 做标准的MVC集成的所有东西 – 注册控制器,设置依赖parsing器等。
  • 使用基础Autofac OWIN集成设置您的应用程序。
  • 添加对Autofac.Mvc5.Owin NuGet包的引用。
  • 在您的应用程序启动类中,在注册基础Autofac中间件后注册Autofac MVC中间件。

     public class Startup { public void Configuration(IAppBuilder app) { var builder = new ContainerBuilder(); // STANDARD MVC SETUP: // Register your MVC controllers. builder.RegisterControllers(typeof(MvcApplication).Assembly); // Run other optional steps, like registering model binders, // web abstractions, etc., then set the dependency resolver // to be Autofac. var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); // OWIN MVC SETUP: // Register the Autofac middleware FIRST, then the Autofac MVC middleware. app.UseAutofacMiddleware(container); app.UseAutofacMvc(); } } 

我也有这样添加的RoleManager包装:

 builder.RegisterType<RoleStore<IdentityRole>>().As<IRoleStore<IdentityRole, string>>(); 

根据SO回答