.net core 如何更新.NET Core 2中Identity User角色的扩展UserRole
我们有一个扩展的身份用户(ApplicationUser),角色(ApplicationRole)和用户角色(ApplicationUserRole) 我们成功地保存了对ApplicationUser的更改,但无法使用以下代码保存对ApplicationUserRole的更改:.net core 如何更新.NET Core 2中Identity User角色的扩展UserRole,.net-core,.net Core,我们有一个扩展的身份用户(ApplicationUser),角色(ApplicationRole)和用户角色(ApplicationUserRole) 我们成功地保存了对ApplicationUser的更改,但无法使用以下代码保存对ApplicationUserRole的更改: public async Task<IActionResult> OnPostAsync(Guid id) { if (!ModelState.IsValid) {
public async Task<IActionResult> OnPostAsync(Guid id)
{
if (!ModelState.IsValid)
{
return Page();
}
var userToUpdate = await _context.Users
.FirstOrDefaultAsync(m => m.Id == id.ToString());
var userRoleToUpdate = await _context.UserRoles
.FirstOrDefaultAsync(m => m.UserId == id.ToString());
// null means User was deleted by another user.
if (userToUpdate == null || userRoleToUpdate == null)
{
return await HandleDeletedUser();
}
// Update the RowVersion to the value when this entity was
// fetched. If the entity has been updated after it was
// fetched, RowVersion won't match the DB RowVersion and
// a DbUpdateConcurrencyException is thrown.
// A second postback will make them match, unless a new
// concurrency issue happens.
_context.Entry(userToUpdate)
.Property("RowVersion").OriginalValue = User.RowVersion;
if (await TryUpdateModelAsync<ApplicationUser>(
userToUpdate,
"User",
s => s.FirstName, s => s.LastName, s => s.Email))
{
try
{
await _context.SaveChangesAsync();
if (await TryUpdateModelAsync<ApplicationUserRole>(
userRoleToUpdate,
"UserRole",
s => s.RoleId.ToString()))
{
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (ApplicationUser)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The user was deleted by another user.");
return Page();
}
var dbValues = (ApplicationUser)databaseEntry.ToObject();
await setDbErrorMessage(dbValues, clientValues, _context);
// Save the current RowVersion so next postback
// matches unless an new concurrency issue happens.
User.RowVersion = (byte[])dbValues.RowVersion;
// Must clear the model error for the next postback.
ModelState.Remove("User.RowVersion");
}
}
return Page();
}
公共异步任务OnPostAsync(Guid id)
{
如果(!ModelState.IsValid)
{
返回页();
}
var userToUpdate=await\u context.Users
.FirstOrDefaultAsync(m=>m.Id==Id.ToString());
var userRoleToUpdate=wait_context.UserRoles
.FirstOrDefaultAsync(m=>m.UserId==id.ToString());
//null表示用户已被其他用户删除。
如果(userToUpdate==null | | userRoleToUpdate==null)
{
return await HandleDeletedUser();
}
//将RowVersion更新为创建此实体时的值
//已获取。如果实体在被获取后已更新
//已获取,RowVersion与DB RowVersion和不匹配
//将引发DbUpdateConcurrencyException。
//第二次回发将使它们匹配,除非有新的回发
//出现并发问题。
_context.Entry(userToUpdate)
.Property(“RowVersion”).OriginalValue=User.RowVersion;
如果(等待TryUpdateModelAsync(
userToUpdate,
“用户”,
s=>s.FirstName,s=>s.LastName,s=>s.Email))
{
尝试
{
wait_context.SaveChangesAsync();
如果(等待TryUpdateModelAsync(
用户角色更新,
“用户角色”,
s=>s.RoleId.ToString())
{
wait_context.SaveChangesAsync();
}
返回页首(“/索引”);
}
捕获(DbUpdateConcurrencyException ex)
{
var exceptionEntry=ex.Entries.Single();
var clientValues=(ApplicationUser)exceptionEntry.Entity;
var databaseEntry=exceptionEntry.GetDatabaseValues();
if(databaseEntry==null)
{
ModelState.AddModelError(string.Empty,“无法保存。”+
“该用户已被其他用户删除。”);
返回页();
}
var dbValues=(ApplicationUser)databaseEntry.ToObject();
等待setDbErrorMessage(dbValues、clientValues、_上下文);
//保存当前行版本以便下次回发
//匹配,除非发生新的并发问题。
User.RowVersion=(字节[])dbValues.RowVersion;
//必须为下一次回发清除模型错误。
ModelState.Remove(“User.RowVersion”);
}
}
返回页();
}
有关于这个的指针吗?我认为我们需要分解保存更改。首先是用户,然后是用户角色,不是吗
另外,我们没有为应用程序角色实现行版本,我认为这太过分了
环境:
.Net核心2.1
更新-1:
例外情况-
InvalidOperationException:传递的表达式节点类型“Call”的表达式无效。仅支持模型属性的简单成员访问表达式
更新-2:
我已更改为此,没有错误,但角色没有更改:
if (await TryUpdateModelAsync<ApplicationUserRole>(
userRoleToUpdate,
"UserRole",
ur => ur.UserId, ur => ur.RoleId))
{
await _context.SaveChangesAsync();
}
if(等待tryupdatemodelsync(
用户角色更新,
“用户角色”,
ur=>ur.UserId,ur=>ur.RoleId)
{
wait_context.SaveChangesAsync();
}
在编辑表单(edit.html)上从下拉列表中更新此角色ID时,我们如何映射工作
角色:
--选择角色--
更新-3:
这很有趣。我将文本从“UserRole”更改为“”:
if(等待tryupdatemodelsync(
用户角色更新,
"",
ur=>ur.RoleId)
{
wait_context.SaveChangesAsync();
}
现在我们有一个错误,我认为这是接近:
InvalidOperationException:实体类型上的属性“RoleId”
“ApplicationUserRole”是密钥的一部分,因此无法修改或删除
标记为修改的。使用更改现有实体的主体
标识外键首先删除依赖项并调用
“SaveChanges”然后将依赖项与新主体关联
这可能是因为我们的ApplicationDBContext中有这个吗?在这种情况下,什么是最好的更新方式呢
protected override void OnModelCreating(ModelBuilder builder)
{
....
// Many to Many relationship - ApplicationUserRole
builder.Entity<ApplicationUserRole>(userRole =>
{
userRole.HasKey(ur => new { ur.UserId, ur.RoleId });
userRole.HasOne(ur => ur.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
userRole.HasOne(ur => ur.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
}
模型创建时受保护的覆盖无效(ModelBuilder)
{
....
//多对多关系-ApplicationUserRole
builder.Entity(userRole=>
{
HasKey(ur=>new{ur.UserId,ur.RoleId});
userRole.HasOne(ur=>ur.Role)
.WithMany(r=>r.UserRoles)
.HasForeignKey(ur=>ur.RoleId)
.IsRequired();
userRole.HasOne(ur=>ur.User)
.WithMany(r=>r.UserRoles)
.HasForeignKey(ur=>ur.UserId)
.IsRequired();
});
}
如果您使用的是AsNetIdentity,看起来您是这样的,那么您应该能够使用UserManager
更新角色。UserManager是Identity的一部分,用于管理用户的身份。只要您的角色是AspNetRoles
,然后注入UserManager
if (await TryUpdateModelAsync<ApplicationUserRole>(
userRoleToUpdate,
"",
ur => ur.RoleId))
{
await _context.SaveChangesAsync();
}
protected override void OnModelCreating(ModelBuilder builder)
{
....
// Many to Many relationship - ApplicationUserRole
builder.Entity<ApplicationUserRole>(userRole =>
{
userRole.HasKey(ur => new { ur.UserId, ur.RoleId });
userRole.HasOne(ur => ur.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
userRole.HasOne(ur => ur.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
}
private readonly UserManager<ApplicationUser> _userManager;
public Controller(UserManager<ApplicationUser> userManger, ApplicationUser applicationUser)
{
_userManager = userManger;
}
public async Task UpDateRole(string userId)
{
var user = await _userManager.FindByIdAsync(userId);
var result = await _userManager.AddToRoleAsync(userId, "RoleName");
}