使用ASP.. NET身份与我自己的实体在MVC

本文关键字:自己的 实体 MVC 我自己 ASP NET 身份 使用 | 更新日期: 2023-09-27 17:50:17

在我的"Car Hire"解决方案中,我有一个单独的项目,其中包含我的所有实体,如用户,角色,汽车,预订等。我首先使用EntityFramework代码来生成数据库。所有这些都运行良好。我已经添加了一个MVC项目到我的解决方案。现在我想充分利用ASP。NET标识2。x模型。我的问题是:我怎么能合并与MVC项目自带的ApplicationUser与我自己的用户类?我的User类:

public partial class User
{
    public User()
    {
    }
    [Key]
    public int Id { get; set; }
    [StringLength(200)]
    public string FirstName { get; set; }
    [StringLength(200)]
    public string LastName { get; set; }
    [StringLength(200)]
    public string Address1 { get; set; }
    [StringLength(200)]
    public string Address2 { get; set; }
    [StringLength(200)]
    public string Address3 { get; set; }
    [StringLength(20)]
    public string ZipCode { get; set; }
    [StringLength(200)]
    public string City { get; set; }
    [StringLength(200)]
    public string Country { get; set; }
    [StringLength(200)]
    public string Phone { get; set; }
    [StringLength(200)]
    public string MobilePhone { get; set; }
    [StringLength(200)]
    public string WorkPhone { get; set; }
}

我是否应该将所有的User属性移动到ApplicationUser类中,并在我自己的类(如Booking类)中为ApplicationUser添加一个外键?

使用ASP.. NET身份与我自己的实体在MVC

ApplicationUser没有什么特别之处。它只是一个从IdentityUser继承的类的默认实现。即使这样,继承也仅仅是引导Identity中的所有功能,如角色、声明等。

您可以完全删除ApplicationUser并使您的用户类继承IdentityUser或者您可以将属性从您的用户类移动到ApplicationUser并删除您的用户类。无论哪种方法,结果都是一样的。

并且,是的,您希望在与"用户"相关的类和最终成为"用户"类的任何类之间创建外键。同样,ApplicationUser没有什么特别之处,所以如果你选择坚持使用它,你可以像在你的项目中设置任何其他POCO一样设置它,根据需要创建与其他实体的关系。

有人建议从ApplicationUser继承你的用户类,但我不认为这是一个好主意。继承用于Identity的"user"基类是有正当理由的,但是这里处理的不是不同类型的用户,而是需要附加属性的一种用户类型。继承实际上只是在无法访问基类并对其进行修改的情况下实现这一目标的一种可接受的方式。在这里,你需要。这是你的课;项目模板只是为您创建了它。

这将是所有用户的基类

public abstract class User : IdentityUser
{
    public abstract string Area { get; }
    public bool IsActiveDirectoryUser { get; private set; }
    protected User(string username, bool isActiveDirectoryUser = false)
        : base(username)
    {
        IsActiveDirectoryUser = isActiveDirectoryUser;
    }
    protected User()
    { }
}

这是一个用户

的例子
public class AdminUser : User
{
    public AdminUser(string username, bool isActiveDirectoryUser = false)
        : base(username, isActiveDirectoryUser)
    { }
    private AdminUser()
    { }
    public override string Area
    {
        get { return UserAreas.Admin; }
    }
}

这是DBContext,映射忽略了user are属性,因为它是硬编码的

    public class IdentityDataContext : IdentityDbContext<User>
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<User>().ToTable("AspNetUsers").Ignore(u => u.Area);
        modelBuilder.Entity<AdminUser>().ToTable("AdminUsers");
    }
}

这是IUserManager的自定义实现。它在实体User上工作,使用我们已经定义的IdentityDataContext和自定义ClaimsFactory(如有必要),如下所示

    public class UserManager
{
    private readonly UserManager<User> _identityManager;
    public UserManager(ClaimsFactory claimsFactory, IdentityDataContext context, IdentityValidator identityValidator)
    {
        _identityManager = new UserManager<User>(new UserStore<User>(context))
                           {
                               ClaimsIdentityFactory = claimsFactory,
                               UserValidator = identityValidator
                           };
    }
    public void Register(User user, string password)
    {
        var result = _identityManager.Create(user, password);
        if (!result.Succeeded)
            throw new ApplicationException("User can not be created. " + result.Errors.FirstOrDefault());
    }
    public void Register(User user)
    {
        var result = _identityManager.Create(user);
        if (!result.Succeeded)
            throw new ApplicationException("User can not be created. " + result.Errors.FirstOrDefault());
    }
    public User Find(string userName, string password)
    {
        return _identityManager.Find(userName, password);
    }
    public ClaimsIdentity CreateIdentity(User user, string applicationCookie)
    {
        return _identityManager.CreateIdentity(user, applicationCookie);
    }
    public User FindByUserName(string userName)
    {
        return _identityManager.FindByName(userName);
    }
    public bool ChangePassword(string identifier, string oldPassword, string newPassword)
    {
        return _identityManager.ChangePassword(identifier, oldPassword, newPassword).Succeeded;
    }
    public bool ResetPassword(string userName, string password)
    {
        try
        {
            var user = FindByUserName(userName);
            var result = _identityManager.RemovePassword(user.Id);
            if (result != IdentityResult.Success)
                return false;
            result = _identityManager.AddPassword(user.Id, password);
            return result == IdentityResult.Success;
        }
        catch (Exception)
        {
            return false;
        }
    }
    public User FindById(string userId)
    {
        return _identityManager.FindById(userId);
    }
    public bool IsInRole(string userId, string role)
    {
        return _identityManager.IsInRole(userId, role);
    }
    public void AddToRole(string userId, string role)
    {
        _identityManager.AddToRole(userId, role);
    }
}

如果您想要索赔,这里是索赔工厂。它将用户区域转换为声明,最后在浏览器中转换为cookie。

    public class ClaimsFactory : ClaimsIdentityFactory<User>
{
    public async override Task<ClaimsIdentity> CreateAsync(UserManager<User> manager, User user, string authenticationType)
    {
        var identity = await base.CreateAsync(manager, user, authenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Area, user.Area, ClaimValueTypes.String));
        return identity;
    }
}

但是,嘿,你能从ApplicationUser到你的User模型建立一个链接吗?

有时候像那样移动代码并不容易。如果是这种情况,你可以这样做:

public class ApplicationUser {
      public virtual YourUserModel userModel { get; set; }
}

希望有帮助!

编辑:

或者,你可以像Callum说的那样,让你的User类继承自IdentityUser:

public class User : IdentityUser {
     //your properties here
}