我正在尝试在我的MVC .NET CORE应用程序中创建一个页面,用户可以在其中更改其他用户的角色。此时视图和模型绑定都很有效,但是当实际尝试将角色保存回数据库时,我收到一条错误消息,指出角色不存在。我的方法是:
我在控制器中的代码如下:
var user = await _userManager.FindByIdAsync(id);
if (user == null)
{
return View("Error");
}
using (_context.Database.BeginTransaction())
{
var removeResult = await _userManager.RemoveFromRolesAsync(user, await _userManager.GetRolesAsync(user));
if (!removeResult.Succeeded)
{
return View("Error");
}
var addResult = await _userManager.AddToRolesAsync(user, model.MemberRoles);
if (!addResult.Succeeded)
{
return View("Error");
}
}
其中model.MemberRoles
为List<string>
个角色。奇怪的是,这个过程在_userManager.RemoveFromRolesAsync
失败,即使我将用户的现有角色直接传递给函数。我试过放弃UserManager
课程和ef一起去但没有运气。我还验证了模型中的角色与数据库中的角色匹配。是否有任何明显错误会导致失败?感谢。
修改
以下是我遇到的错误:
InvalidOperationException: Role ADMINISTRATOR does not exist.
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`4.<AddToRoleAsync>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
以下是我的数据库中定义的角色:
答案 0 :(得分:5)
当您尝试将用户添加到角色时,它首先尝试查找角色。在Sql Profiler中,您可以看到它实际上是通过NormalizedName字段而不是Name字段进行搜索。
exec sp_executesql N'
SELECT TOP(2) [r].[Id], [r].[ConcurrencyStamp], [r].[Name], [r].[NormalizedName]
FROM [AspNetRoles] AS [r]
WHERE [r].[NormalizedName] = @__normalizedRoleName_0',N'@__normalizedRoleName_0 nvarchar(256)',@__normalizedRoleName_0=N'ADMINISTRATOR'
解决方案是在创建角色时将NormalizedName字段设置为Name字段的大写:
所以在SeedData类中:
/* Create Roles */
IEnumerable<UserRole> allRoles = Enum.GetValues(typeof(UserRole)).Cast<UserRole>();
foreach (UserRole role in allRoles)
{
if (!await roleManager.RoleExistsAsync(role.ToString()))
{
await roleManager.CreateAsync(new IdentityRole {
Name = role.ToString(),
NormalizedName = role.ToString().ToUpper()
});
}
}
答案 1 :(得分:2)
我真的很惊讶你没有得到InvalidCastException
,因为无法直接将string[]
投射到List<string>
。我不确定你为什么一开始就这样做,因为如果你想要一个清单,你就可以轻松地拨打.ToList()
而不是.ToArray()
,并称之为一天。或者,由于GetRolesAsync
的返回类型为IList<string>
,无论如何,您甚至不需要这样做。现在,这是我看到你的代码唯一的问题。