asp.net mvc - Cómo configurar ASP.NET Identity ApplicationUserManager con StructureMap
asp.net-mvc dependency-injection (1)
Estoy usando asp.net identidad en mi proyecto y usando structuremap como marco DI. el problema es que cuando uso la inyección de constructor, ApplicationUserManager no configura todos sus miembros, por ejemplo, TokenProvider, ...
esta es mi clase ApplicationUserManager:
public class ApplicationUserManager : UserManager<User, long>
{
public ApplicationUserManager(IUserStore<User, long> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new CustomUserStore(context.Get<InsuranceManagementContext>()));
// Configure the application user manager
manager.UserValidator = new UserValidator<User, long>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
manager.PasswordValidator = new PasswordValidator
{
RequireDigit = true,
RequiredLength = 8,
RequireLowercase = false,
RequireNonLetterOrDigit = true,
RequireUppercase = false
};
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<User, long>(dataProtectionProvider.Create("TEST"));
}
return manager;
}
}
esta es la clase Startup.Auth:
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(InsuranceManagementContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
ExpireTimeSpan = TimeSpan.FromHours(2.0),
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
});
}
}
y es mi AccountController:
public class AccountController : BaseController
{
private ApplicationUserManager _userManager;
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
public AccountController(ApplicationUserManager userManager)
{
UserManager = userManager;
}
}
mi pregunta es ¿cómo puedo configurar mi ApplicationUserManager con structuremap? si lo configuro como el siguiente código funciona, pero no sé si es una buena solución o no:
ObjectFactory.Initialize(x =>
{
...
x.For<ApplicationUserManager>().Use(() => HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>());
...
});
por favor insinúe si hay una solución mejor y si está bien, ¿cuál es la mejor vida para ello? HttpContextScope, Singleton, ...?
Antes de crear la configuración de StructureMap para esto, es útil saber cómo la crearía manualmente, es decir, si realmente "actualiza" todo usted mismo.
UserManager tiene una dependencia en IUserStore, y su implementación EntityFramework (UserStore) tiene una dependencia en DbContext. Hacer todo manualmente se vería así:
var dbContext = new IdentityDbContext("Your ConnectionString Name");
var userStore = new UserStore<IdentityUser>(dbContext);
var userManager = new UserManager<IdentityUser>(userStore);
(Reemplace IdentityUser
con su usuario personalizado, si está usando uno)
A continuación, puede configurar UserManager
esta manera:
userManager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6
};
La parte más complicada sobre la configuración de userManager está relacionada con el UserTokenProvider (que usa la API de protección de datos); si lo hiciera manualmente, se vería así :
var dataProtectionProvider = new DpapiDataProtectionProvider("Application name");
var dataProtector = dataProtectionProvider.Create("Purpose");
userManager.UserTokenProvider = new DataProtectorTokenProvider<IdentityUser>(dataProtector);
Aquí hay un ejemplo de un registro de StructureMap (puede extrapolar de este ejemplo y adaptarlo a sus propias necesidades):
public DefaultRegistry() {
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
For<IUserStore<IdentityUser>>()
.Use<UserStore<IdentityUser>>()
.Ctor<DbContext>()
.Is<IdentityDbContext>(cfg => cfg.SelectConstructor(() => new IdentityDbContext("connection string")).Ctor<string>().Is("IdentitySetupWithStructureMap"));
ForConcreteType<UserManager<IdentityUser>>()
.Configure
.SetProperty(userManager => userManager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6
})
.SetProperty(userManager => userManager.UserValidator = new UserValidator<IdentityUser>(userManager));
}
Escribí una publicación de blog sobre esto , explica el proceso que condujo a esta configuración, también hay un enlace a un ejemplo en github de un proyecto de MVC donde, usando esta configuración, puede crear, enumerar y eliminar usuarios.