ApplicationUserManager 不使用我的自定义 UserStore 实现

ApplicationUserManager doesn't use my custom UserStore implementation

我使用 ASP.NET 标识创建了一个新的 MVC5 应用程序。我没有更改很多文件。这是我得到的错误:

项目中的以下更改与 VisualStudio 模板不同:

ApplicationUserManager.cs

public class ApplicationUserManager : UserManager<User>
{
    public ApplicationUserManager(IUserStore<User> userStore)
        : base(userStore)
    {
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        // Use DI to resolve the UserStore
        var userStore = (IUserStore<User>) DependencyResolver.Current.GetService(typeof (IUserStore<User>));

        var manager = new ApplicationUserManager(userStore);

        // rest is same as in the template ...
    }
}

我的 DependencyResolver 是 Ninject。我为它创建了以下绑定:

Bind<IMyDbContextFactory>().To<MyDbContextFactory>().InSingletonScope();
Bind<IUserStore<User>>().To<UserStore>().WithConstructorArgument("factory", factory => Kernel.Get<MyDbContextFactory>());

UserStore.cs

public class UserStore : IUserStore<User>,
    IUserLockoutStore<User, string>,
    IUserPasswordStore<User>,
    IUserTwoFactorStore<User, string>,
    IUserEmailStore<User>
{
    private readonly IMyDbContextFactory _factory;

    public UserStore(IMyDbContextFactory factory)
    {
        _factory = factory;
    }

    public void Dispose()
    {
        // Nothing to dispose here
    }

    public Task CreateAsync(User user)
    {
        using (var context = _factory.CreateContext())
        {
            // TODO: Validation
            context.Users.Add(user);
            var result = context.SaveChanges();
            return Task.FromResult(result);
        }
    }

    // the rest of the implementend methods from the interfaces ...
}

为了完整起见,我在 UserStore.cs

中使用用户实体、DbContext 和工厂来检索 DbContext

User.cs

public class User : IUser
{
    public string Id { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public object PhoneNumber { get; set; }
    public int AccessFailedCount { get; set; }
    public bool LockoutEnabled { get; set; }
    public DateTime? LockoutEndDateUtc { get; set; }
    public bool TwoFactorEnabled { get; set; }

    public virtual ICollection<UserRole> ApplicationUserRoles { get; set; }
    public virtual ICollection<UserLogin> ApplicationUserLogins { get; set; }
}

MyDbContextFactory.cs

public class MyDbContextFactory : IMyDbContextFactory
{
    public IMyDbContext CreateContext()
    {
        return new MyDbContext();
    }
}

MyDbContext.cs

public class MyDbContext : DbContext, IMyDbContext
{
    public MyDbContext()
        : base("MyDbContextConnection")
    {
        Configuration.LazyLoadingEnabled = false;
        Configuration.ProxyCreationEnabled = false;

        Database.Initialize(true);
    }

    // DbSets, OnModelCreating and other stuff ...
}

异常暗示 UserManager 为空。但事实并非如此:

似乎 ApplicationUserManager 并没有真正使用(或设置)我注入的 UserStore。但这是为什么呢?

好的,我找到了,但这很难。

ApplicationUserManager 调用的 UserStore 的第一个方法是 SetPasswordHashAsync。 (不要问我为什么-.-)

我对该方法的实施返回了 null。这是错误的,原因有二

  1. 我不应该写 return null; 而是 return Task.FromResult<Task>(null);,因为它是一个异步方法。 (或抛出异常)。正因为如此,我收到了那个没用的YSOD。
  2. UserManager 首先调用 SetPasswordHashAsync。再一次,不要问我为什么。由于我是使用 /Account/Register Action 来注册新用户的,所以我根本没想到 UserManager 首先尝试设置密码。我的意思是,还没有用户。这就是为什么我想注册一个。 WTF?

总结一下:UserManager 确实使用了我的 UserStore,但不是我预期的那样。