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
。这是错误的,原因有二
- 我不应该写
return null;
而是 return Task.FromResult<Task>(null);
,因为它是一个异步方法。 (或抛出异常)。正因为如此,我收到了那个没用的YSOD。
- UserManager 首先调用
SetPasswordHashAsync
。再一次,不要问我为什么。由于我是使用 /Account/Register
Action 来注册新用户的,所以我根本没想到 UserManager 首先尝试设置密码。我的意思是,还没有用户。这就是为什么我想注册一个。 WTF?
总结一下:UserManager 确实使用了我的 UserStore,但不是我预期的那样。
我使用 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
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
。这是错误的,原因有二
- 我不应该写
return null;
而是return Task.FromResult<Task>(null);
,因为它是一个异步方法。 (或抛出异常)。正因为如此,我收到了那个没用的YSOD。 - UserManager 首先调用
SetPasswordHashAsync
。再一次,不要问我为什么。由于我是使用/Account/Register
Action 来注册新用户的,所以我根本没想到 UserManager 首先尝试设置密码。我的意思是,还没有用户。这就是为什么我想注册一个。 WTF?
总结一下:UserManager 确实使用了我的 UserStore,但不是我预期的那样。