我定制了身份系统的一些功能以满足我的需求。
我有以下ApplicationUserManager:
public class ApplicationUserManager : UserManager<ApplicationUser, long>
{
public ApplicationUserManager()
: base(new UserStore<ApplicationUser, ApplicationRole,
long, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(new GestkatDbContext()))
{
//PasswordValidator = new MinimumLengthValidator(10);
}
public ApplicationUserManager(IUserStore<ApplicationUser,long> store)
: base(store)
{
}
public static ApplicationUserManager Create(
IdentityFactoryOptions<ApplicationUserManager> options,
IOwinContext context)
{
var manager = new ApplicationUserManager(
new UserStore<ApplicationUser, ApplicationRole, long, ApplicationUserLogin,
ApplicationUserRole,ApplicationUserClaim>(
context.Get<GestkatDbContext>()));
// Configure validation logic for usernames
manager.UserValidator =
new UserValidator<ApplicationUser,long>(manager)
{
AllowOnlyAlphanumericUserNames = false,
//RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
return manager;
}
public bool CreateUser(ApplicationUser user, string password)
{
var idResult = this.Create(user, password);
return idResult.Succeeded;
}
public bool AddUserToRole(long userId, string roleName)
{
return this.AddToRole(userId, roleName).Succeeded;
}
public bool ClearAllUserRoles(long userId)
{
foreach (var role in this.GetRoles(userId))
{
if (!this.RemoveFromRole(userId, role).Succeeded)
{
return false;
}
}
return true;
}
}
其他自定义类是:
public class ApplicationUser : IdentityUser<long, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
public virtual UserInfo UserInfo { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
// Note the authenticationType must match the one
// defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity =
await manager.CreateIdentityAsync(this,
DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class ApplicationRole : IdentityRole<long, ApplicationUserRole>
{
public ApplicationRole() : base() { }
public ApplicationRole(string name, string description)
{
this.Name = name;
this.Description = description;
}
public virtual string Description { get; set; }
}
public class ApplicationUserRole : IdentityUserRole<long> { }
public class ApplicationUserClaim : IdentityUserClaim<long> { }
public class ApplicationUserLogin : IdentityUserLogin<long> { }
添加用户并将其添加到角色似乎工作正常。我的问题是当我想从角色中删除用户时。
当我想将用户添加到角色列表中时,我开始使用方法ClearAllUserRoles(long userId)
清除用户所在的所有角色,然后将其添加到每个所选角色。像这样:
public ActionResult UserRoles_Update(long RolesSelectedUserId, List<long> SelectedUserRoles)
{
if (RolesSelectedUserId == 0)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
userInfoRepository = new GenericRepository<UserInfo>(DB);
UserInfo uInfo = userInfoRepository.GetByID(RolesSelectedUserId);
UserManager.ClearAllUserRoles(uInfo.UserLoginInfo.Id);
foreach (var roleId in SelectedUserRoles)
{
var roleName = DB.Roles.FirstOrDefault(m => m.Id == roleId).Name;
if (!UserManager.AddUserToRole(uInfo.UserLoginInfo.Id, roleName))
{
return Json(false);
}
}
return Json(true);
}
我的问题是RemoveFromRole(userId, role)
中使用的ClearAllUserRoles(long userId)
方法只将ApplicationUser_Id
表的字段ApplicationRole_Id
和AspNetUserRoles
置为空,只留下字段当我尝试将用户重新分配给他已经处于以下异常中的角色时,UserId
和RoleId
已填充:
{"Violation of PRIMARY KEY constraint 'PK_dbo.AspNetUserRoles'. Cannot insert duplicate key in object 'dbo.AspNetUserRoles'. The duplicate key value is (16, 1).\r\nThe statement has been terminated."}
我的问题是:
我的AspNetUserRoles
表格应该包含这4列(ApplicationUser_Id
,ApplicationRole_Id
,UserId
,RoleId
)还是我做错了我的数据库上下文的OnModelCreating()
方法?
RemoveFromRole(userId, role)
方法是否按预期工作,或者应该删除AspNetUserRoles
表的所有行?
更新
这是我的OnModelCreating()
方法:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
{
throw new ArgumentNullException("modelBuilder");
}
EntityTypeConfiguration<ApplicationUser> table =
modelBuilder.Entity<ApplicationUser>().ToTable("AspNetUsers");
table.Property((ApplicationUser u) => u.UserName).IsRequired();
modelBuilder.Entity<ApplicationUser>().HasMany<ApplicationUserRole>((ApplicationUser u) => u.Roles);
modelBuilder.Entity<ApplicationUserRole>().HasKey((ApplicationUserRole r) =>
new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("AspNetUserRoles");
EntityTypeConfiguration<ApplicationUserLogin> entityTypeConfiguration =
modelBuilder.Entity<ApplicationUserLogin>().HasKey((ApplicationUserLogin l) =>
new
{
UserId = l.UserId,
LoginProvider = l.LoginProvider,
ProviderKey
= l.ProviderKey
}).ToTable("AspNetUserLogins");
EntityTypeConfiguration<IdentityUserClaim> table1 =
modelBuilder.Entity<IdentityUserClaim>().ToTable("AspNetUserClaims");
EntityTypeConfiguration<ApplicationRole> entityTypeConfiguration1 =
modelBuilder.Entity<ApplicationRole>().ToTable("AspNetRoles");
entityTypeConfiguration1.Property((ApplicationRole r) => r.Name).IsRequired();
modelBuilder.Entity<ApplicationUser>()
.HasRequired(p => p.UserInfo).WithOptional(p => p.UserLoginInfo);
}
在我的迁移中,create table是这样的:
CreateTable(
"dbo.AspNetUserRoles",
c => new
{
UserId = c.Long(nullable: false),
RoleId = c.Long(nullable: false),
ApplicationUser_Id = c.Long(),
ApplicationRole_Id = c.Long(),
})
.PrimaryKey(t => new { t.UserId, t.RoleId })
.ForeignKey("dbo.AspNetUsers", t => t.ApplicationUser_Id)
.ForeignKey("dbo.AspNetRoles", t => t.ApplicationRole_Id)
.Index(t => t.ApplicationUser_Id)
.Index(t => t.ApplicationRole_Id);
答案 0 :(得分:2)
您需要覆盖OnModelBuilding
替换
modelBuilder.Entity<ApplicationUser>().HasMany<ApplicationUserRole>((ApplicationUser u) => u.Roles);
与
modelBuilder.Entity<ApplicationUser>().HasMany(p => p.Roles).WithRequired().HasForeignKey(p => p.UserId);
modelBuilder.Entity<ApplicationRole>().HasMany(p => p.Users).WithRequired().HasForeignKey(p => p.RoleId);
但是,我建议您在方法开始时调用base.OnModelCreating(modelBuilder);
,并让股票IdentityDbContext为您完成大部分操作。