MVC5:UserManager.AddToRole():“将用户添加到角色时出错:找不到UserId”?
我一直在尝试使用MVC5 / EF6并尝试使用Code-First Migrations进行新的身份validation。 解决方案中的所有内容当前正在构建,我可以添加Migration
,但是当我通过VS2013中的package manager console
执行update-database
,我的Configuration.cs
文件无法将我的测试数据完全处理到我的表中并输出Error Adding User to Role: UserId not found
。
我已经尝试显式设置用户ID并让它由Manager生成(如某些示例所示),但每次收到相同的错误消息。 我知道我的Configuration.cs
文件的#region User & User Roles
中的错误是失败的,但我不确定原因:
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework; using PersonalPortfolio2.Helper; using PersonalPortfolio2.Models; using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Diagnostics; using System.Linq; namespace PersonalPortfolio2.Models { public sealed class Configuration : DbMigrationsConfiguration { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(PersonalPortfolio2.Models.ApplicationDbContext context) { BlobHelper bh = new BlobHelper(); //LocationHelper lh = new LocationHelper(); ApplicationDbContext db = new ApplicationDbContext(); #region Roles try { List myRoles = new List(new string[] { "Root", "Admin", "Outsider", "Client", "Primary" }); var RoleManager = new RoleManager(new RoleStore(context)); foreach (string r in myRoles) { RoleManager.Create(new IdentityRole(r)); } } catch (Exception ex) { throw new Exception("Error Create Roles: " + ex.Message); } #endregion #region User & User Roles var store = new UserStore(context); var manager = new UserManager(store); List myUsers = GetTestUsers(); var passwordHasher = new PasswordHasher(); foreach (var u in myUsers) { var userExists = db.Users.Where(a => a.Email == u.Email).FirstOrDefault(); if (userExists == null) { var user = new ApplicationUser { Email = u.Email, PasswordHash = passwordHasher.HashPassword("P@ssword1"), LockoutEnabled = false, Name = u.Name, Position = u.Position, RegisteredDate = DateTime.Now, LastVisitDate = DateTime.Now, OrganizationId = u.OrganizationId, ProfilePictureSrc = u.ProfilePictureSrc, }; try { var userCreateResult = manager.Create(user); } catch (Exception ex) { throw new Exception("Error Add User: " + ex.Message + "\n" + ex.InnerException); } // Add User to Roles List usersRoles = GetUserRoles(u.Email); bool codeHit = false; foreach (string role in usersRoles) { try { codeHit = true; manager.AddToRole(user.Id, role); } catch (Exception ex) { // ERROR! throw new Exception("Error Adding User to Role: " + ex.Message + "\n" + ex.Data + "\n" + ex.InnerException + "\nName: " + user.Name + "\nEmail: " + user.Email + "\nuser.ID: " + user.Id + "\nu.Id: " + u.Id + "\nRole: " + role + "\nCodeHit: " + codeHit); } } } } #endregion } #region Helpers private List GetTestUsers() { List testUsers = new List { new ApplicationUser { Id = "1", Email = "Admin@abc.com", Name = "Admin User", RegisteredDate = System.DateTime.Now, LastVisitDate = System.DateTime.Now, Position = "Site Administrator", PhoneNumber = "1234564321", }, new ApplicationUser { Id = "2", Email = "first.last@hotmail.com", Name = "James Woods", RegisteredDate = System.DateTime.Now, LastVisitDate = System.DateTime.Now, Position = "Software Developer / Web Designer", PhoneNumber = "1234567890", }, new ApplicationUser { Id = "3", Email = "tyler.perry@gmail.com", Name = "Tyler Perry", RegisteredDate = System.DateTime.Now, LastVisitDate = System.DateTime.Now, Position = "Company Contact", PhoneNumber = "1234567890", } }; return testUsers; } public List GetUserRoles(string user) { List myRoles = new List(); switch (user) { //"Root", "Admin", "Outsider", "Client", "Primary" case "Admin@abc.com": myRoles = new List(new string[] { "Root", "Admin" }); break; case "first.last@hotmail.com": myRoles = new List(new string[] { "Admin" }); break; case "tyler.perry@gmail.com": myRoles = new List(new string[] { "Client", "Outsider" }); break; default: myRoles = new List(new string[] {"[user] not found."}); break; } return myRoles; } #endregion } }
任何人都可以通过我可能忽略的内容提供一些见解吗? 有关完整的详细信息,我当前的catch
语句输出如下:
Error Adding User to Role: UserId not found. System.Collections.ListDictionaryInternal Name: Admin User Email: Admin@abc.com user.ID: 1 u.Id: 1 Role: Root CodeHit: True
当我注释掉显式Id = "1",
对于我的管理员用户, user.ID
和u.Id
变为: ab753316-3d7b-4f98-a13a-d19f7c926976
。 我曾经以为它可能是我的帮助方法GetTestUsers()
或GetUserRoles(u.Email)
这个问题,但在我的try/catch
和我正在使用的codeHit
布尔变量之间,我已经validation了问题肯定来自manager.AddToRole(user.Id, role)
。
我将此留给这里可能有类似问题的人。 我有完全相同的“症状”。 事实certificate,与存储的密码相关的问题不符合配置的密码策略(至少一个大写字符,一个小写字符等等)。
根据以下注释和答案,通常,当不遵循任何用户创建约束或策略时,将抛出相同的模糊错误消息。
这可能包括以下内容:
- 未遵循密码政策(这似乎是最常见的原因)
- 必填字段作为空字符串/ null传递
- 用户名或电子邮件重复
实际上存在许多可能导致此错误发生的问题。 如果上述问题无法解决您的问题,我建议如下:
- 熟悉为您的解决方案设置的identityprovider的规则和策略
- 根据@Ted在下面的回答,在UserManager.Create方法上跟踪或设置断点以查看结果,因为这可能会揭示问题的原因。
CraftBeerHipsterDude的回答帮助我找到了我遇到的相同情况的答案。 如果AddToRole失败,那么诀窍是查看从Usermanager.Create(…)返回的结果。 它可能不会抛出exception,但仍会返回表示创建失败的结果。 在我的情况下,它是“用户名已存在”。
概括:检查早期操作的结果以追踪实际错误。
对问题创建者的回答:不应输入UserId,将其留给entity framework为用户创建它。您也尝试将其作为整数输入,但基于角色的安全性中的用户ID是GUID以字符串的forms,所以无论如何都不能尝试为期望字符串的列添加整数值。
现在这对我来说不是问题,但我遇到了同样错误的其他几个问题:
我试图弄清楚我错过了什么,但没有发现任何错误。
所以我使用VS的另一个实例作为种子代码的调试器(在另一个线程中找到):
if (System.Diagnostics.Debugger.IsAttached == false) System.Diagnostics.Debugger.Launch();
我注意到用户在添加到角色时确实有一个Id。 最后,我能够通过添加一个空的catch块来解决这个问题。代码不会因为错误而抛出exception,并且用户被添加到正确的角色:
try { var newUser = userManager.FindByEmail(superuserToInsert.Email); userManager.AddToRole(newUser.Id, "Super users"); } catch { }
在我尝试将新创建的用户添加到角色之前,种子似乎回滚了用户的创建,并且从未在用户数据库中创建用户。
但是当我完全删除添加到角色部分时,用户被添加到数据库中,并且在第二次运行一些编辑后的配置代码时,用户可能被添加到角色中,导致我认为这是一个错误的错误抛出..用空catch块忽略这个错误错误似乎也忽略了用户创建的回滚(这必须发生在添加到角色部分之前的窗帘后面)导致用户存在时添加到角色部分的码。
希望它可以帮到某人
编辑:
以上几乎解决了我所有的头疼,但我注意到仍然有大约300个帐户无法创建(但没有抛出错误)。 一个简单的FULL OUTER JOIN和使用源数据库表检查用户数据库使我认为用户在“UserName”和“Email”列的值中都带有短划线( – )字符,从而阻止了用户的创建,这个是这样的。
这是一个简单的修复,只是将用户管理器配置为使用超过字母数字字符:(即使属性名称似乎只指向“用户名”,它也影响“电子邮件”)
var userManager = new UserManager(userStore); userManager.UserValidator = new UserValidator
// Miske
我会避免在Seed方法中使用UserManager和RoleManager 。 相反,我只会使用上下文。 我使用的是以下创建用户并将其分配给角色的内容:
protected override void Seed(DbModelContext context) { if (context == null) { throw new ArgumentNullException("context", "Context must not be null."); } const string UserName = "User"; const string RoleName = "UserRole"; var userRole = new IdentityRole { Name = RoleName, Id = Guid.NewGuid().ToString() }; context.Roles.Add(userRole); var hasher = new PasswordHasher(); var user = new IdentityUser { UserName = UserName, PasswordHash = hasher.HashPassword(UserName), Email = "test@test.com", EmailConfirmed = true, SecurityStamp = Guid.NewGuid().ToString() }; user.Roles.Add(new IdentityUserRole { RoleId = userRole.Id, UserId = user.Id }); context.Users.Add(user); base.Seed(context); }
Entity类是自定义实现(因为我想使用GUID作为ID),但它们派生自框架类。 如果将它们更改为适当的框架类,它应该以相同的方式工作。
编辑
我删除了自定义类并将它们切换到框架类,因为有一些混乱。
- 在ASP.Net Identity(MVC)中的“注册”期间保存其他配置文件数据
- ASP.NET Core Identity不会注入UserManager
- ASP.NET Identity(使用IdentityServer4)获取外部资源oauth访问令牌
- 将ASP.NET标识集成到现有的DbContext中
- 使用Identity 2.0数据库来validationASP.NET Core 1.0应用程序
- 在实现自己的IUserStore时,类上的“可选”接口实际上是可选的吗?
- 交换Azure Web App部署槽会注销ASP.NET Core RC2中的所有用户
- 在ASP.NET身份中获取使用Microsoft帐户进行身份validation的用户的电子邮件
- 如何在MVC应用程序中使用JWT进行身份validation和授权?