如何制作编辑用户页面以从同一视图编辑用户详细信息和角色?
How do you make an Edit User page to edit user details and roles from the same view?
我有一个可能很简单的问题,但我似乎无法找到答案并且一直走入死胡同。我只想创建一个视图,我可以在其中从一个视图编辑用户信息和用户角色。我被告知了很多事情,并指出创建一个视图模型,以及简单的无关信息。我看过很多关于如何仅编辑用户信息或仅编辑用户角色的指南,但这些指南出现在单独的视图中,我找不到任何指向在单个视图中完成此操作的内容。
到目前为止我有什么
- 用户信息模型
- 用户角色模型
- 用户管理控制器
- 编辑用户视图
- UserDetaulsViewModel
我可以列出所有用户及其角色,只是在创建用户或编辑用户时看不到要列出的角色。每次我试着说
通过 ID 查找此用户 - 没问题
通过 id 查找此用户角色 - 没问题
但是系统中有多个角色,我似乎无法获得要填充的字符串和列表。它要么为控制器弹出我,要么为视图中的每个语句弹出我。
public async Task<IActionResult> EditUser(string id)
{
var user = await _userManager.FindByIdAsync(id);
var viewModel = new ApplicationUser();
{
viewModel.FirstName = user.FirstName;
viewModel.LastName = user.LastName;
viewModel.UserName = user.UserName;
}
var model = new List<UserRoles>();
foreach (var role in _roleManager.Roles)
{
var roleModel = new UserRoles
{
RoleId = role.Id,
RoleName = role.Name
};
if (await _userManager.IsInRoleAsync(user, role.Name))
{
roleModel.Selected = true;
}
else
{
roleModel.Selected = false;
}
model.Add(roleModel);
UserDetailsViewModel userDetailsViewModel = new UserDetailsViewModel()
{
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
RoleName = roleModel
};
return View(viewModel);
}
@使用Rabbit.Application.ViewModels
@model UserDetailsViewModel
<h1 class="bg-info text-white">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-action="Update" method="post">
<div class="form-group">
<label asp-for="@Model.UserName"></label>
<input asp-for="@Model.UserName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="@Model.FirstName"></label>
<input asp-for="@Model.FirstName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="@Model.LastName"></label>
<input asp-for="@Model.LastName" class="form-control" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input name="password" class="form-control" />
<div class="card-body">
@for (int i = 0; i < Model.Count; i++)
{
<div class="form-check m-1">
<input type="hidden" asp-for="@Model[i].RoleName" />
<input asp-for="@Model[i].Selected" class="form-check-input" />
<label class="form-check-label" asp-for="@Model[i].Selected">
@Model[i].RoleName
</label>
</div>
}
<div asp-validation-summary="All" class="text-danger"></div>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
我的demo如下实现你的效果:
HomeController.cs:
public IActionResult Index( )
{
// var role1 = new Role() { RoleId = "a1", Name = "a1" };
// var role2 = new Role() { RoleId = "a2", Name = "a2" };
// var A1User = new User()
//{
// UserId = "A1",
// UserName = "A1",
// FirstName = "A1",
// LastName = "A1",
// Password = "A1"
//};
//var pslist = new List<UserRole>()
// { new UserRole(){User=A1User, Role=role1},
// new UserRole(){User=A1User, Role=role2}
// };
// _context.UserRole.AddRange(pslist);
// _context.SaveChanges();
var user = _context.User.Include(u => u.UserRole).ThenInclude(u => u.Role).FirstOrDefault();
var userRoles = new HashSet<string>(user.UserRole.Select(c => c.RoleId));
var allrole = _context.Role.Select(c => new RoleViewModel()
{
RoleId = c.RoleId,
Name = c.Name,
Selected = userRoles.Contains(c.RoleId)
}).ToList();
var userDetaulsViewModel = new UserDetaulsViewModel();
userDetaulsViewModel.User = user;
userDetaulsViewModel.RoleViewModel = allrole;
PopulateAssignedRoleData(user);
return View(userDetaulsViewModel);
}
private void PopulateAssignedRoleData(User user)
{
var allRoles = _context.Role;
var userRoles = new HashSet<string>(user.UserRole.Select(c => c.RoleId));
var roleViewModel = new List<RoleViewModel>();
foreach (var role in allRoles)
{
roleViewModel.Add(new RoleViewModel
{
RoleId = role.RoleId,
Name = role.Name,
Selected = userRoles.Contains(role.RoleId)
});
}
ViewData["Roles"] = roleViewModel;
}
private void UpdateUserRole(string[] selectedRoles, User userToUpdate)
{
if (selectedRoles == null)
{
userToUpdate.UserRole = new List<UserRole>();
return;
}
var selectedRolesHS = new HashSet<string>(selectedRoles);
var userRoles = new HashSet<string>(userToUpdate.UserRole.Select(c => c.Role.RoleId));
foreach (var role in _context.Role)
{
if (selectedRolesHS.Contains(role.RoleId))
{
if (!userRoles.Contains(role.RoleId))
{
userToUpdate.UserRole.Add(new UserRole { UserId = userToUpdate.UserId, RoleId = role.RoleId });
}
}
else
{
if (userRoles.Contains(role.RoleId))
{
UserRole roleToRemove = userToUpdate.UserRole.FirstOrDefault(i => i.RoleId == role.RoleId);
_context.Remove(roleToRemove);
}
}
}
}
[HttpPost]
public async Task<IActionResult> Update( string[] selectedRoles)
{ var userToUpdate = _context.User.Include(i=>i.UserRole).ThenInclude(i => i.Role).FirstOrDefault();
UpdateUserRole(selectedRoles, userToUpdate);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
PopulateAssignedRoleData(userToUpdate);
return RedirectToAction(nameof(Index));
}
Index.cshtml:
@model EditWithUser6.ViewModels.UserDetaulsViewModel
<h1 class="bg-info text-white">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-controller="home" asp-action="Update" method="post">
<div class="form-group">
<label asp-for="User.UserName"></label>
<input asp-for="User.UserName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="User.FirstName"></label>
<input asp-for="User.FirstName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="User.LastName"></label>
<input asp-for="User.LastName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="User.Password"></label>
<input asp-for="User.Password" class="form-control" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
List<EditWithUser6.ViewModels.RoleViewModel> roles = ViewBag.Roles;
foreach (var role in roles)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedRoles"
value="@role.RoleId"
@(Html.Raw(role.Selected ? "checked=\"checked\"" : "")) />
@role.RoleId /*@: @role.Name*/ add id or name or both
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<button type="submit" class="btn btn-primary">Save</button>
<input type="hidden" asp-for="User.UserId" />
</form>
Role.cs:
public class Role
{
public string RoleId { get; set; }
public string Name { get; set; }
public virtual List<UserRole> UserRole { get; set; }
}
User.cs:
public class User
{
public string UserId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public virtual List<UserRole> UserRole { get; set; }
}
用户Role.cs:
public class UserRole
{
[Key]
public string UserId { get; set; }
public User User { get; set; }
[Key]
public string RoleId { get; set; }
public Role Role { get; set; }
}
EditWithUser6Context.cs:
public class EditWithUser6Context: DbContext
{
public EditWithUser6Context(DbContextOptions<EditWithUser6Context> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
public DbSet<Role> Role { get; set; }
public DbSet<UserRole> UserRole { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<UserRole>().HasKey(i => new { i.UserId, i.RoleId });
}
}
RoleViewModel.cs:
public class RoleViewModel
{
public string RoleId { get; set; }
public bool Selected { get; set; }
public string Name { get; set; }
}
UserDetaulsViewModel.cs:
public class UserDetaulsViewModel
{
public User User { get; set; }
public List<RoleViewModel> RoleViewModel { get; set; }
}
结果:
我有一个可能很简单的问题,但我似乎无法找到答案并且一直走入死胡同。我只想创建一个视图,我可以在其中从一个视图编辑用户信息和用户角色。我被告知了很多事情,并指出创建一个视图模型,以及简单的无关信息。我看过很多关于如何仅编辑用户信息或仅编辑用户角色的指南,但这些指南出现在单独的视图中,我找不到任何指向在单个视图中完成此操作的内容。
到目前为止我有什么
- 用户信息模型
- 用户角色模型
- 用户管理控制器
- 编辑用户视图
- UserDetaulsViewModel
我可以列出所有用户及其角色,只是在创建用户或编辑用户时看不到要列出的角色。每次我试着说
通过 ID 查找此用户 - 没问题 通过 id 查找此用户角色 - 没问题
但是系统中有多个角色,我似乎无法获得要填充的字符串和列表。它要么为控制器弹出我,要么为视图中的每个语句弹出我。
public async Task<IActionResult> EditUser(string id)
{
var user = await _userManager.FindByIdAsync(id);
var viewModel = new ApplicationUser();
{
viewModel.FirstName = user.FirstName;
viewModel.LastName = user.LastName;
viewModel.UserName = user.UserName;
}
var model = new List<UserRoles>();
foreach (var role in _roleManager.Roles)
{
var roleModel = new UserRoles
{
RoleId = role.Id,
RoleName = role.Name
};
if (await _userManager.IsInRoleAsync(user, role.Name))
{
roleModel.Selected = true;
}
else
{
roleModel.Selected = false;
}
model.Add(roleModel);
UserDetailsViewModel userDetailsViewModel = new UserDetailsViewModel()
{
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
RoleName = roleModel
};
return View(viewModel);
}
@使用Rabbit.Application.ViewModels
@model UserDetailsViewModel
<h1 class="bg-info text-white">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-action="Update" method="post">
<div class="form-group">
<label asp-for="@Model.UserName"></label>
<input asp-for="@Model.UserName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="@Model.FirstName"></label>
<input asp-for="@Model.FirstName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="@Model.LastName"></label>
<input asp-for="@Model.LastName" class="form-control" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input name="password" class="form-control" />
<div class="card-body">
@for (int i = 0; i < Model.Count; i++)
{
<div class="form-check m-1">
<input type="hidden" asp-for="@Model[i].RoleName" />
<input asp-for="@Model[i].Selected" class="form-check-input" />
<label class="form-check-label" asp-for="@Model[i].Selected">
@Model[i].RoleName
</label>
</div>
}
<div asp-validation-summary="All" class="text-danger"></div>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
我的demo如下实现你的效果:
HomeController.cs:
public IActionResult Index( )
{
// var role1 = new Role() { RoleId = "a1", Name = "a1" };
// var role2 = new Role() { RoleId = "a2", Name = "a2" };
// var A1User = new User()
//{
// UserId = "A1",
// UserName = "A1",
// FirstName = "A1",
// LastName = "A1",
// Password = "A1"
//};
//var pslist = new List<UserRole>()
// { new UserRole(){User=A1User, Role=role1},
// new UserRole(){User=A1User, Role=role2}
// };
// _context.UserRole.AddRange(pslist);
// _context.SaveChanges();
var user = _context.User.Include(u => u.UserRole).ThenInclude(u => u.Role).FirstOrDefault();
var userRoles = new HashSet<string>(user.UserRole.Select(c => c.RoleId));
var allrole = _context.Role.Select(c => new RoleViewModel()
{
RoleId = c.RoleId,
Name = c.Name,
Selected = userRoles.Contains(c.RoleId)
}).ToList();
var userDetaulsViewModel = new UserDetaulsViewModel();
userDetaulsViewModel.User = user;
userDetaulsViewModel.RoleViewModel = allrole;
PopulateAssignedRoleData(user);
return View(userDetaulsViewModel);
}
private void PopulateAssignedRoleData(User user)
{
var allRoles = _context.Role;
var userRoles = new HashSet<string>(user.UserRole.Select(c => c.RoleId));
var roleViewModel = new List<RoleViewModel>();
foreach (var role in allRoles)
{
roleViewModel.Add(new RoleViewModel
{
RoleId = role.RoleId,
Name = role.Name,
Selected = userRoles.Contains(role.RoleId)
});
}
ViewData["Roles"] = roleViewModel;
}
private void UpdateUserRole(string[] selectedRoles, User userToUpdate)
{
if (selectedRoles == null)
{
userToUpdate.UserRole = new List<UserRole>();
return;
}
var selectedRolesHS = new HashSet<string>(selectedRoles);
var userRoles = new HashSet<string>(userToUpdate.UserRole.Select(c => c.Role.RoleId));
foreach (var role in _context.Role)
{
if (selectedRolesHS.Contains(role.RoleId))
{
if (!userRoles.Contains(role.RoleId))
{
userToUpdate.UserRole.Add(new UserRole { UserId = userToUpdate.UserId, RoleId = role.RoleId });
}
}
else
{
if (userRoles.Contains(role.RoleId))
{
UserRole roleToRemove = userToUpdate.UserRole.FirstOrDefault(i => i.RoleId == role.RoleId);
_context.Remove(roleToRemove);
}
}
}
}
[HttpPost]
public async Task<IActionResult> Update( string[] selectedRoles)
{ var userToUpdate = _context.User.Include(i=>i.UserRole).ThenInclude(i => i.Role).FirstOrDefault();
UpdateUserRole(selectedRoles, userToUpdate);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
PopulateAssignedRoleData(userToUpdate);
return RedirectToAction(nameof(Index));
}
Index.cshtml:
@model EditWithUser6.ViewModels.UserDetaulsViewModel
<h1 class="bg-info text-white">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-controller="home" asp-action="Update" method="post">
<div class="form-group">
<label asp-for="User.UserName"></label>
<input asp-for="User.UserName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="User.FirstName"></label>
<input asp-for="User.FirstName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="User.LastName"></label>
<input asp-for="User.LastName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="User.Password"></label>
<input asp-for="User.Password" class="form-control" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
List<EditWithUser6.ViewModels.RoleViewModel> roles = ViewBag.Roles;
foreach (var role in roles)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedRoles"
value="@role.RoleId"
@(Html.Raw(role.Selected ? "checked=\"checked\"" : "")) />
@role.RoleId /*@: @role.Name*/ add id or name or both
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<button type="submit" class="btn btn-primary">Save</button>
<input type="hidden" asp-for="User.UserId" />
</form>
Role.cs:
public class Role
{
public string RoleId { get; set; }
public string Name { get; set; }
public virtual List<UserRole> UserRole { get; set; }
}
User.cs:
public class User
{
public string UserId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public virtual List<UserRole> UserRole { get; set; }
}
用户Role.cs:
public class UserRole
{
[Key]
public string UserId { get; set; }
public User User { get; set; }
[Key]
public string RoleId { get; set; }
public Role Role { get; set; }
}
EditWithUser6Context.cs:
public class EditWithUser6Context: DbContext
{
public EditWithUser6Context(DbContextOptions<EditWithUser6Context> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
public DbSet<Role> Role { get; set; }
public DbSet<UserRole> UserRole { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<UserRole>().HasKey(i => new { i.UserId, i.RoleId });
}
}
RoleViewModel.cs:
public class RoleViewModel
{
public string RoleId { get; set; }
public bool Selected { get; set; }
public string Name { get; set; }
}
UserDetaulsViewModel.cs:
public class UserDetaulsViewModel
{
public User User { get; set; }
public List<RoleViewModel> RoleViewModel { get; set; }
}
结果: