结构图和Aspnet.Identity UserManager静态类问题

Pau*_*ski 5 c# structuremap static inversion-of-control asp.net-mvc-5

我在我的帐户控制器中获取正确的UserManager实例时遇到了问题.目前,我无法重置密码以作为我的提供商工作,其他设置被忽略.

在Startup - void ConfigureAuth(IAppBuilder app)中我有以下内容:

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

然后在AccountManager类中,上面引用的方法Create包含以下内容:

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    // Configure the application user manager
    public ApplicationUserManager(ApplicationUserStore store)
        : base(store)
    {
    }

public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new ApplicationUserStore(new ViewingBookerDatabaseContext()));

        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = false,
            RequireDigit = false,
            RequireLowercase = false,
            RequireUppercase = false,
        };
        // Configure user lockout defaults
        manager.UserLockoutEnabledByDefault = true;
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        manager.MaxFailedAccessAttemptsBeforeLockout = 5;

        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }
Run Code Online (Sandbox Code Playgroud)

现在,在安装IoC之前,这种方法很有用 - 在本例中是StrcutureMap.控制器的IoC以下列模式注册:

Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.With(new ControllerConvention());
        });

public class ControllerConvention : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (type.CanBeCastTo(typeof(Controller)) && !type.IsAbstract)
        {
            registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我的AccountController中引用UserManager,如下所示:

private ApplicationUserManager _userManager;
    public ApplicationUserManager UserManager
    {
        get
        {
            return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }

    private IAuthenticationManager _authenticationManager
    {
        get
        {
            return HttpContext.GetOwinContext().Authentication;
        }
    }

    public AccountController() 
    {
    }

    public AccountController(ApplicationUserManager userManager, ViewingBookerDatabaseContext context, CurrentUser currentUser, Logger logger, EmailService emailService)
    {
        UserManager = userManager;
        _context = context;
        _currentUser = currentUser;
        _logger = logger;
        _emailService = emailService;
    }
Run Code Online (Sandbox Code Playgroud)

现在,UserManager用于我的密码重置,帐户创建等.安装IoC后,我收到"没有ITokenProvider已注册"密码重置,带有@的帐户名称在创建用户时返回为无效等.看起来像AccountController的实例ApplicationUserManager不是通过ApplicationUserManager类的Create()方法创建的.

任何人都可以指向我对结构图的正确实现,因此它调用Create来获取AccountUserManager的实例,而不是返回不包含ITokenProvider规范的该类的通用实例.等等?

谢谢你的帮助.

Pau*_*ski 4

好了朋友们。由于这么长时间没有人回复,必须做一些进一步的研究并提出以下可能不是最优雅的解决方案:

1. Startup.cs - 删除以下行

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

2.在Startup.cs中引入新变量

公共静态 IDataProtectionProvider DataProtectionProvider { 获取;私人套装;}

然后,在 public void ConfigureAuth(IAppBuilder app) 中将其设置为以下内容:

DataProtectionProvider = app.GetDataProtectionProvider();

3. ApplicationUserManager 或无论您如何称呼它,删除静态 Create 方法并将其构造函数更改为以下内容:

         public ApplicationUserManager(ApplicationUserStore store)
        : base(store)
    {
        // Configure validation logic for usernames
        UserValidator = new UserValidator<ApplicationUser>(this)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        // Configure validation logic for passwords
        PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = false,
            RequireDigit = false,
            RequireLowercase = false,
            RequireUppercase = false,
        };

        // Configure user lockout defaults
        UserLockoutEnabledByDefault = true;
        DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        MaxFailedAccessAttemptsBeforeLockout = 5;
    }
Run Code Online (Sandbox Code Playgroud)

对于密码重置 ITokenProvider,只需引用 Startup 的 DataProtectionProvider 变量,如下所示:

    if (Startup.DataProtectionProvider != null)
            UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(Startup.DataProtectionProvider.Create("ASP.NET Identity"));
Run Code Online (Sandbox Code Playgroud)

最后...

在 AccountController.cs 中 - 删除对 ApplicationUserManager 的 getter 的任何引用,并重用 StructureMap 在控制器的构造函数中提供的实例。

 public AccountController(ApplicationUserManager userManager)
    {
        _userManager = userManager;
Run Code Online (Sandbox Code Playgroud)

所以你将调用 _userManager 对象方法

   REMOVE IF YOU HAVE IT IN YOUR CONTROLLER:
   public ApplicationUserManager UserManager
{
    get
    {
        return _userManager ??    HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}
Run Code Online (Sandbox Code Playgroud)