我一直在尝试使用MVC5 / EF6并尝试使用Code-First Migrations进行新的身份验证。解决方案中的所有内容当前都在构建,我可以添加Migration
,但是当我在VS2013中通过update-database
执行package manager console
时,我的Configuration.cs
文件无法完全处理我的Error Adding User to Role: UserId not found
将数据测试到我的表和输出#region User & User Roles
。
我已尝试显式设置用户ID并让它由Manager生成(如某些示例所示),但每次收到相同的错误消息。我知道我的Configuration.cs
文件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<PersonalPortfolio2.Models.ApplicationDbContext>
{
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<string> myRoles = new List<string>(new string[] { "Root", "Admin", "Outsider", "Client", "Primary" });
var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(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<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
List<ApplicationUser> 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<string> 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<ApplicationUser> GetTestUsers()
{
List<ApplicationUser> testUsers = new List<ApplicationUser>
{
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<string> GetUserRoles(string user)
{
List<string> myRoles = new List<string>();
switch (user)
{
//"Root", "Admin", "Outsider", "Client", "Primary"
case "Admin@abc.com":
myRoles = new List<string>(new string[] { "Root", "Admin" });
break;
case "first.last@hotmail.com":
myRoles = new List<string>(new string[] { "Admin" });
break;
case "tyler.perry@gmail.com":
myRoles = new List<string>(new string[] { "Client", "Outsider" });
break;
default:
myRoles = new List<string>(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
和我正在使用的manager.AddToRole(user.Id, role)
布尔变量之间,我已经验证了问题肯定来自{{1}}。
答案 0 :(得分:28)
我将此处留给可能遇到类似问题的人。我有完全相同的“症状”。事实证明,与存储的密码相关的问题不符合配置的密码策略(至少一个大写字符,一个小写字符等等)。
根据以下注释和答案,一般情况下,如果不遵循任何用户创建约束或策略,则会抛出相同的模糊错误消息。
这可能包括以下内容:
实际上存在许多可能导致此错误发生的问题。如果上述问题无法解决您的问题,我建议如下:
答案 1 :(得分:11)
CraftBeerHipsterDude的回答帮助我找到了同样情况的答案。如果AddToRole失败,那么诀窍是查看从Usermanager.Create(...)返回的结果。它可能不会抛出异常,但仍返回表示创建失败的结果。就我而言,它是“用户名已经存在”。
概括:检查早期操作的结果以追踪实际错误。
答案 2 :(得分:5)
对问题创建者的回答:不应输入UserId,将其留给实体框架为用户创建..您还尝试将其作为整数输入,但基于角色的安全性的用户ID是字符串形式的GUID,因此无论如何都不能尝试为期望字符串的列添加整数值。
现在这对我来说不是问题,但我还有其他一些问题出现同样的错误:
我试图弄清楚我错过了什么,但没有发现任何错误。
所以我使用VS的另一个实例作为种子代码的调试器(在另一个线程中找到):
if (System.Diagnostics.Debugger.IsAttached == false)
System.Diagnostics.Debugger.Launch();
我注意到用户在添加到角色时确实有一个Id。 最后,我能够通过添加一个空的catch块来解决这个问题。由于错误的错误并且用户被添加到正确的角色,代码不会抛出异常:
try
{
var newUser = userManager.FindByEmail(superuserToInsert.Email);
userManager.AddToRole(newUser.Id, "Super users");
}
catch
{
}
在我尝试将新创建的用户添加到角色之前,种子似乎回滚了用户的创建,并且从未在用户数据库中创建用户。
但是当我完全删除添加到角色部分时,用户被添加到数据库中,并且在第二次运行一些编辑后的配置代码时,用户可能被添加到角色中,这使我认为它是aa抛出错误的错误。用空catch块忽略这个错误错误似乎也忽略了用户创建的回滚(这必须发生在添加到角色部分之前的窗帘后面)导致用户在添加角色时存在部分代码。
希望它有助于某人
编辑:
以上几乎解决了我所有的头痛,但我注意到仍然有大约300个帐户无法创建(但没有错误抛出)。一个简单的FULL OUTER JOIN并使用源数据库表检查用户数据库,这使我认为在“UserName”和“Email”列的值中都带有短划线( - )字符的用户停止了用户的创建,这个是这样的。
这是一个简单的修复,只需将用户管理器配置为使用超过字母数字的字符: (即使属性名称似乎只指向“用户名”,它也会影响“电子邮件”)
var userManager = new UserManager<ApplicationUser>(userStore);
userManager.UserValidator = new UserValidator<ApplicationUser(userManager)
{
AllowOnlyAlphanumericUserNames = false,
};
// Miske
答案 3 :(得分:4)
我会避免在种子方法中使用 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),但它们派生自框架类。如果将它们更改为适当的框架类,它应该以相同的方式工作。
修改强>
我删除了自定义类并将它们切换到框架类,因为存在一些混淆。
答案 4 :(得分:0)
这挽救了我的第二天。谢谢@达菲朋克。就我而言,问题是密码。以前是“ abc”。
var studentPassword = "abcABC_9";
var user = new ApplicationUser { UserName = "abc", Email = 1@gmail.com };
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var result = await UserManager.CreateAsync(user, studentPassword.ToString());
await UserManager.AddToRoleAsync(user.Id, "Student");
答案 5 :(得分:0)
在我的情况下,问题是我使用用户的(Username)代替ID,工作代码如下:
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Username, Email = model.Username, workshopId =model.workshopId};
var rolesList = _context.Roles.ToList();
string role = rolesList.FirstOrDefault(r => r.Id == model.SelectedRoleId).Name;
var result = await UserManager.CreateAsync(user, model.Password);
// Add User to the selected role from the list in .cshtml
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
result =await UserManager.AddToRoleAsync(user.Id, role);
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}