tutorial tables net mvc español asp asp.net asp.net-mvc asp.net-identity owin

asp.net - tables - Cómo enchufar mi contenedor Autofac en ASP. Identidad de red 2.1



asp.net identity tutorial español (5)

He estado investigando las nuevas características de la nueva versión de ASP.NET Identity 2.1 y una de sus mejoras son las nuevas características de IoC integradas en OWIN Middleware. Una de las oraciones que busqué en los ejemplos es esta:

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

Esta oración recibe un delegado de función que devuelve una nueva instancia de implementación de administrador proporcionada en los ejemplos:

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

Personalmente, no me gusta esta implementación porque no puedo usar un contenedor para inyectar cualquier dependencia que desee para estos administradores.

También hay un "IdentityFactoryOptions" y un "IOwinContext" que se inyectan "mágicamente" a la función que no puedo extraer en mi contenedor de IoC.

¿Alguien tiene una mejor solución en esta implementación?


A modo de referencia, aquí se explica cómo puede cablear todo usando 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));


Ahora detallado para la integración de MVC5 Owin en Autofac Docs :

"

  • Haga todo lo necesario para la integración estándar de MVC: registrar controladores, establecer la resolución de la dependencia, etc.
  • Configure su aplicación con la integración Autofac OWIN base.
  • Agregue una referencia al paquete Autofac.Mvc5.Owin NuGet.
  • En la clase de inicio de la aplicación, registre el middleware Autofac MVC después de registrar el middleware base de Autofac.

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

    "

También tengo el contenedor RoleManager así que agregué:

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

según la respuesta SO


Estoy comenzando desde una instalación de MVC5 lista para usar y utilizando AutoFac como un contenedor de IoC. Parece que estoy tratando de lograr un objetivo similar al tuyo, así que déjame explicarte lo que hice. Como descargo de responsabilidad, soy bastante nuevo en el uso de IoC y en Identity.

Creo que el IOwinContext es innecesario en un rol como IoC si está utilizando el suyo propio. Cambié para registrar mi ApplicationUserManager con AutoFac. Para lograr esto tuve que:

Elimine las líneas CreatePerOwinContext de Startup.Auth, ya que registraré ApplicationDbContext y ApplicationUserManager en AutoFac.

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

Modifique los argumentos del constructor ApplicationUserManager e incluya todo desde la función Crear.

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

Configure AccountController para que un único constructor tome un ApplicationUserManager como argumento y UserManager propiedad UserManager que toma el ApplicationUserManager del OwinContext .

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

Registre todo con AutoFac, incluida una instancia de 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>();

Ese es el resumen aproximado. Puede que me haya perdido un par de otros ajustes que tuve que hacer en el camino.


La respuesta de Ben tiene la idea general correcta, pero instancia manualmente el DbContext y usa esta instancia cuando registra el resto de los tipos. OMI, esa es una mala idea (no se debe usar el mismo contexto de db eterno para TODAS las solicitudes).

El comentario de Derek es una gran mejora, pero no transfiere el contexto de la base de datos al almacén de usuarios, lo que genera errores como "El tipo de entidad ApplicationUser no es parte del modelo para el contexto actual".

He incluido mi código a continuación, como referencia, es muy similar al de 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​") });


Logré la solución utilizando el localizador de servicios autofac:

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

Sí, no es lo suficientemente bueno, pero mientras tanto, podríamos usar el mismo alcance del objeto declarado en el proceso de registro de autofac.