环境准备:
1、VS 2022 免费社区版
本章目标:
1、增加 用户 列表显示页面;
2、增加 角色 维护主页面;
3、增加 编辑 角色下属 用户 界面;
4、
1、增加 用户列表 显示页面
新建一个 UserAdmin的控制器:

就选择 MVC 控制器-空:

名称: UserAdminController

打开UserAdminController.cs后,在默认的 Index 右键选择 添加视图:

简单一点,就用空视图:

名字不用改,就Index.cshtml

会自动在 Views目录下,增加 UserAdmin 目录,并增加空的 Index.cshtml ,并自动打开:

在Index.cshtml 视图中插入 显示用户列表的 View,代码如下:
@using Microsoft.AspNetCore.Identity
@model IEnumerable<IdentityUser>
@{
ViewBag.Title = "Index";
}
<div class="panel panel-primary">
<div class="panel-heading">
用户列表
</div>
<table class="table table-striped">
<tr><th>Name</th><th>Email</th><th>PhoneNumber</th><th></th></tr>
@if (Model.Count() == 0)
{
<tr><td colspan="4" class="text-center">无用户</td></tr>
}
else
{
foreach (IdentityUser user in Model)
{
<tr>
<td>@user.UserName</td>
<td>@user.Email</td>
<td>@user.PhoneNumber</td>
<td>
@Html.ActionLink("密码重置", "ResetPassword", new { id = user.Id },
new { @class = "btn btn-warning btn-xs" })
@Html.ActionLink("编辑", "Edit", new { id = user.Id },
new { @class = "btn btn-primary btn-xs" })
@Html.ActionLink("删除", "Delete", new { id = user.Id },
new { @class = "btn btn-danger btn-xs" })
</td>
</tr>
}
}
</table>
</div>
修改 UserAdminController ,先把 UserManager 传入,再修改 Index View的返回为所有 User:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace POSystem.Controllers
{
public class UserAdminController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
public UserAdminController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
public IActionResult Index()
{
return View(_userManager.Users);
}
}
}
先把这个UserAdmin的按钮入口 放在 Home和Privacy菜单的中间,修改_Layout.cshtml
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="UserAdmin" asp-action="Index">用户管理</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
列表效果:

注:密码重置、编辑、删除 待补充。
2、增加 角色 维护主页面;
增加一个角色维护管理页面来为用户分配角色;先添加一个RoleAdminController 控制器:

同样再加个Index View:

修改 RoleAdminController, 传入 RoleManager, Index返回所有Role给View:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace POSystem.Controllers
{
public class RoleAdminController : Controller
{
private readonly RoleManager<IdentityRole> _roleManager;
public RoleAdminController(RoleManager<IdentityRole> roleManager)
{
_roleManager = roleManager;
}
public IActionResult Index()
{
return View(_roleManager.Roles);
}
}
}
修改Index View,先最简单的显示一个列表:
@using Microsoft.AspNetCore.Identity
@model IEnumerable<IdentityRole>
@{
ViewBag.Title = "Index";
}
<div class="panel panel-primary">
<div class="panel-heading">
角色列表
</div>
<table class="table table-striped">
<tr><th>Name</th><th></th></tr>
@if (Model.Count() == 0)
{
<tr><td colspan="4" class="text-center">无角色</td></tr>
}
else
{
foreach (IdentityRole role in Model)
{
<tr>
<td>@role.Name</td>
<td>
@Html.ActionLink("编辑", "Edit", new { id = role.Id },
new { @class = "btn btn-primary btn-xs" })
@Html.ActionLink("删除", "Delete", new { id = role.Id },
new { @class = "btn btn-danger btn-xs" })
</td>
</tr>
}
}
</table>
</div>@Html.ActionLink("新建", "Create","RoleAdmin",null, new { @class = "btn btn-primary btn-xs" })
继续修改 _Layout.cshtml :
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="UserAdmin" asp-action="Index">用户管理</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="RoleAdmin" asp-action="Index">角色管理</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
跑起来看到有角色管理这个按钮了:

但是一点就出错:

初步研究,应该是没有加这个:
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>();
加完,能正常显示RoleAdmin的Index:

在RoleAdmin 控制器中增加 Create Action :
public ActionResult Create()
{
return View();
}
[HttpPost]
public async Task<ActionResult> Create([Required] string name)
{
if (ModelState.IsValid)
{
IdentityResult result = await _roleManager.CreateAsync(new IdentityRole(name));
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
AddErrorsFromResult(result);
}
}
return View();
}
private void AddErrorsFromResult(IdentityResult result)
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
再为Create Action 添加一个空视图,并把以下视图代码加入:
@model string
@{ ViewBag.Title = "新增角色";}
<h2>新增角色</h2>
@Html.ValidationSummary(false)
@using (Html.BeginForm())
{
<div class="form-group">
<label>Name</label>
<input name="name" value="@Model" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">新增</button>
@Html.ActionLink("取消", "Index", "RoleAdmin", null, new { @class = "btn btn-default btn-xs" })
}
运行后,点击 新建 按钮:

建一个 Admin 、ReadOnlyUser 、OperationUser :

3、增加 编辑 角色下属 用户 界面;
考虑在角色界面,显示每个角色对应的用户;并增加角色维护用户页面(即 编辑 页面)
先增加两个ViewModel:
using Microsoft.AspNetCore.Identity;
namespace POSystem.Models
{
public class RoleViewModel
{
public IdentityRole Role { get; set; }
public IEnumerable<IdentityUser> Members { get; set; }
public IEnumerable<IdentityUser> NonMembers { get; set; }
}
}
using System.ComponentModel.DataAnnotations;
namespace POSystem.Models
{
public class RoleModificationModel
{
[Required]
public string RoleName { get; set; }
public string[]? IdsToAdd { get; set; }
public string[]? IdsToDelete { get; set; }
}
}
private readonly RoleManager<IdentityRole> _roleManager;
private readonly UserManager<IdentityUser> _userManager;
public RoleAdminController(RoleManager<IdentityRole> roleManager, UserManager<IdentityUser> userManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
RoleAdmin改写成以上,首先是把 RoleManager<IdentityRole> roleManager, UserManager<IdentityUser> userManager 传进来;
增加 Edit 两个Action, 一个HTTP GET 一个对应HTTP POST:
public async Task<ActionResult> Edit(string id)
{
IdentityRole role = await _roleManager.FindByIdAsync(id);
IEnumerable<IdentityUser> members
= await _userManager.GetUsersInRoleAsync(role.Name);
List<IdentityUser> nonMembers = new List<IdentityUser>();
foreach (IdentityUser user in _userManager.Users)
{
if (!members.Any(x => x.Id.Equals(user.Id)))
{
nonMembers.Add(user);
}
}
return View(new RoleViewModel
{
Role = role,
Members = members,
NonMembers = nonMembers
});
}
[HttpPost]
public async Task<ActionResult> Edit(RoleModificationModel model)
{
IdentityResult result;
if (ModelState.IsValid)
{
foreach (string userId in model.IdsToAdd ?? new string[] { })
{
var user = await _userManager.FindByIdAsync(userId);
result = await _userManager.AddToRoleAsync(user, model.RoleName);
if (!result.Succeeded)
{
return View("Error", result.Errors);
}
}
foreach (string userId in model.IdsToDelete ?? new string[] { })
{
var user = await _userManager.FindByIdAsync(userId);
result = await _userManager.RemoveFromRoleAsync(user,
model.RoleName);
if (!result.Succeeded)
{
return View("Error", result.Errors);
}
}
return RedirectToAction("Index");
}
return View("Error", new string[] { "Role Not Found" });
}
增加Edit的视图,用空视图,然后用以下代码代替:
@using POSystem.Models
@using Microsoft.AspNetCore.Identity
@model RoleViewModel
@{ ViewBag.Title = "Edit Role";}
@Html.ValidationSummary()
@using (Html.BeginForm())
{
<input type="hidden" name="roleName" value="@Model.Role.Name" />
<div class="panel panel-primary">
<div class="panel-heading">添加用户至角色:@Model.Role.Name</div>
<table class="table table-striped">
@if (Model.NonMembers.Count() == 0)
{
<tr><td colspan="2">所有用户已添加</td></tr>
}
else
{
<tr><td>用户名</td><td>添加至角色</td></tr>
foreach (IdentityUser user in Model.NonMembers)
{
<tr>
<td>@user.UserName</td>
<td>
<input type="checkbox" name="IdsToAdd" value="@user.Id">
</td>
</tr>
}
}
</table>
</div>
<div class="panel panel-primary">
<div class="panel-heading">从角色:@Model.Role.Name 中移除用户</div>
<table class="table table-striped">
@if (Model.Members.Count() == 0)
{
<tr><td colspan="2">无下属用户</td></tr>
}
else
{
<tr><td>用户名</td><td>从角色中移除</td></tr>
foreach (IdentityUser user in Model.Members)
{
<tr>
<td>@user.UserName</td>
<td>
<input type="checkbox" name="IdsToDelete" value="@user.Id">
</td>
</tr>
}
}
</table>
</div>
<button type="submit" class="btn btn-primary">保存</button>
@Html.ActionLink("取消", "Index", null, null, new { @class = "btn btn-default" })
}
点击 ReadOnlyUser 角色的编辑按钮,可以勾选用户添加至角色:

上一步点保存后,再点击 ReadOnlyUser 角色的编辑按钮,可以看到 已经在角色列表,并可以勾选移除:


为了直观的显示每个角色下面有哪些用户,则考虑修改Index Action和视图:
public async Task<IActionResult> Index()
{
List<RoleViewModel> roleviewmodels = new List<RoleViewModel>();
foreach (IdentityRole role in _roleManager.Roles.ToList())
{
RoleViewModel newrole = new RoleViewModel();
newrole.Role = role;
newrole.Members = await _userManager.GetUsersInRoleAsync(role.Name);
roleviewmodels.Add(newrole);
}
return View(roleviewmodels);
}
此处有个 MySQL 和 MSSQL不同的地方,如果红色的 .ToList() 不加,则会报错,提示:
InvalidOperationException: This MySqlConnection is already in use. See https://fl.vu/mysql-conn-reuse
最后经过查询,知道MySQL不支持一个特性:MultipleActiveResultSets
修改Index 视图如下:
@using Microsoft.AspNetCore.Identity
@model IEnumerable<RoleViewModel>
@{
ViewBag.Title = "Index";
}
<div class="panel panel-primary">
<div class="panel-heading">
角色列表
</div>
<table class="table table-striped">
<tr><th>角色名</th><th>下属用户</th><th></th></tr>
@if (Model.Count() == 0)
{
<tr><td colspan="4" class="text-center">无角色</td></tr>
}
else
{
foreach (RoleViewModel roleview in Model)
{
<tr>
<td>@roleview.Role.Name</td>
<td>
@foreach (IdentityUser user in @roleview.Members)
{
@user.UserName@Html.Label(";")
}
</td>
<td>@Html.ActionLink("编辑", "Edit", new { id = roleview.Role.Id },new { @class = "btn btn-primary btn-xs" })
@Html.ActionLink("删除", "Delete", new { id = roleview.Role.Id },new { @class = "btn btn-danger btn-xs" })
</td>
</tr>
}
}
</table>
</div>
@Html.ActionLink("新建", "Create","RoleAdmin",null, new { @class = "btn btn-primary btn-xs" })
最后体现结果:

原创文章,作者:jamestackk,如若转载,请注明出处:https://blog.ytso.com/tech/database/273744.html