篇(15)-入门实战-权限管理之用户创建与关联角色(ViewModel再用与模型验证一
篇(15)-Asp.Net Core入门实战-权限管理之用户创建与关联角色(ViewModel再用与模型验证一)在上个篇章中,讲了角色和菜单的关系(也就是给角色赋权),本章讲用户和给用户分派角色的功能。如果是小白,最好是仔细看我写的代码,因为关键代码处都有注解。建议将篇14和篇15阅读完毕再做演练,为防止单篇过长,我将其分成2篇来讲解。
用户与角色的处理逻辑是:(1).用户的增删改查;(2).给用户选一个所属角色。
1.用户管理功能
(1).用户表(Sql库)的创建
https://img2022.cnblogs.com/blog/39139/202211/39139-20221119164729546-1778510452.jpg
CREATE TABLE .(
IDENTITY(1,1) NOT NULL,
NOT NULL,
(32) NOT NULL,
(128) NOT NULL,
(256) NULL,
(32) NULL,
(16) NULL,
(128) NULL,
NULL,
(64) NULL,
NULL,
NOT NULL,
NOT NULL,
NULL,
NULL,
NOT NULL,
NOT NULL,
(128) NULL,
CONSTRAINT PRIMARY KEY NONCLUSTERED
(
ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON
) ON
GO
(2).用户Model的编写,这个Model直接与Sql表的结构一致。
public class Manager
{
/// <summary>
/// 主键 MaxLength属性作用于字符串,不能用在int类型上
/// </summary>
public int Id { get; set; }
/// <summary>
/// 角色ID
/// </summary>
public int RoleId { get; set; }
/// <summary>
/// 用户名
/// </summary>
public String UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public String Password { get; set; }
/// <summary>
/// 头像
/// </summary>
public String Avatar { get; set; }
/// <summary>
/// 用户昵称
/// </summary>
public String NickName { get; set; }
/// <summary>
/// 手机号码
/// </summary>
public String Mobile { get; set; }
/// <summary>
/// 邮箱地址
/// </summary>
public String Email { get; set; }
/// <summary>
/// 登录次数
/// </summary>
public int? LoginCount { get; set; }
/// <summary>
/// 最后一次登录IP
/// </summary>
public String LoginLastIp { get; set; }
/// <summary>
/// 最后一次登录时间
/// </summary>
public DateTime? LoginLastTime { get; set; }
/// <summary>
/// 添加人
/// </summary>
public int AddManagerId { get; set; }
/// <summary>
/// 添加时间
/// </summary>
public DateTime AddTime { get; set; }
/// <summary>
/// 修改人
/// </summary>
public int? ModifyManagerId { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public DateTime? ModifyTime { get; set; }
/// <summary>
/// 是否锁定
/// </summary>
public Boolean IsLock { get; set; }
/// <summary>
/// 是否删除
/// </summary>
public Boolean IsDelete { get; set; }
/// <summary>
/// 备注
/// </summary>
public String Remark { get; set; }
}
(3).用户View部分的编写
(3.1)视图View部分包括用户的增、删、改、查功能,还有对应的修改用户角色,修改用户密码。
https://img2022.cnblogs.com/blog/39139/202211/39139-20221119164729137-595455668.jpg
(3.2)Create视图代码如下
https://img2022.cnblogs.com/blog/39139/202211/39139-20221119164729482-1540972877.jpg
@{ ViewData["Title"] = "新建用户"; }
@model RegisterManagerView
@section Scripts{
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
<form action="/Manager/Create" method="post">
@Html.AntiForgeryToken()
<label asp-for="UserName">用户名</label>
<input type="text" asp-for="UserName" name="UserName" placeholder="用户名">
<span asp-validation-for="UserName" class="text-danger"></span>
<label asp-for="Password">密码</label>
<input type="password" asp-for="Password" name="Password" placeholder="密码" />
<span asp-validation-for="Password" class="text-danger"></span>
<label asp-for="ConfirmPassword">确认密码</label>
<input type="password" asp-for="ConfirmPassword" name="ConfirmPassword" placeholder="确认密码" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
<label asp-for="Mobile">手机号</label>
<input type="text" asp-for="Mobile" name="Mobile" placeholder="手机号">
<span asp-validation-for="Mobile" class="text-danger"></span>
<label asp-for="Email">Email</label>
<input type="text" asp-for="Email" name="Email" placeholder="邮箱">
<span asp-validation-for="Email" class="text-danger"></span>
<label asp-for="Remark">介绍</label>
<textarea name="Remark" asp-for="Remark" placeholder="相关介绍"></textarea>
<button type="submit">确定</button>
<button type="reset">重置</button>
</form>
(3.3)Edit视图代码如下
https://img2022.cnblogs.com/blog/39139/202211/39139-20221119164729249-1554954533.jpg
@{ ViewData["Title"] = "编辑用户"; }
@model EditManagerView
@section Scripts{
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
<form action="/Manager/Edit" method="post">
@Html.AntiForgeryToken()
<label asp-for="UserName">用户名</label>
<input type="text" asp-for="UserName" name="UserName" placeholder="用户名">
<span asp-validation-for="UserName" class="text-danger"></span>
<input type="hidden" asp-for="Id" />
<label asp-for="Mobile">手机号</label>
<input type="text" asp-for="Mobile" name="Mobile" placeholder="手机号">
<span asp-validation-for="Mobile" class="text-danger"></span>
<label asp-for="Email">Email</label>
<input type="text" asp-for="Email" name="Email" placeholder="邮箱">
<span asp-validation-for="Email" class="text-danger"></span>
<label asp-for="Remark">介绍</label>
<textarea name="Remark" asp-for="Remark" placeholder="相关介绍"></textarea>
<button type="submit">确定</button>
<button type="reset">重置</button>
</form>
(3.4)Index视图代码如下(列表页)
https://img2022.cnblogs.com/blog/39139/202211/39139-20221119164729799-1270171401.jpg
@using Humanizer;
@using RjWebCms.Db;
@model PaginatedList<PageManager>
@{
ViewData["Title"] = "用户列表";
}
@section Scripts{
}
@Html.AntiForgeryToken()
<form asp-action="Index" method="get">
<table>
<tr><td><a asp-controller="Manager" asp-action="Create">添加</a></td></tr>
<tr>
<td>查询关键词:<input type="text" name="SearchString" value="@ViewData["CurrentFilter"]" /></td>
<td><input type="submit" value="查询" /></td>
<td><a asp-action="Index">Back</a></td>
<td><a id="DelAll" name="DelAll">批量删除</a></td>
</tr>
</table>
</form>
<table class="table table-hover">
<thead>
<tr>
<td>✔</td>
<td><a asp-action="Index" asp-route-sortOrder="@ViewData["NameSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">用户名</a></td>
<td>角色名</td>
<td>手机号</td>
<td><a asp-action="Index" asp-route-sortOrder="@ViewData["DateSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">时间</a></td>
<td>操作</td>
</tr>
@foreach (var item in Model)
{
<tr>
<td><input type="checkbox" class="done-checkbox" name="chk_ids" value="@item.Id"></td>
<td>@item.UserName</td>
<td>@item.RoleName</td>
<td>@item.Mobile</td>
<td>@item.AddTime</td>
<td>
<a asp-controller="Manager" asp-action="Details" asp-route-id="@item.Id">View</a>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a>
<a asp-action="ChangeRole" asp-route-id="@item.Id">ChangeRole</a>
<a asp-action="ChangePass" asp-route-id="@item.Id">ChangePass</a>
<a asp-controller="Manager" asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</thead>
</table>
@{
var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.HasNextPage ? "disabled" : ""; ;
}
<a asp-action="Index"
asp-route-sortOrder="@ViewData["CurrentSort"]"
asp-route-pageNumber="@(Model.PageIndex - 1)"
asp-route-currentFilter="@ViewData["CurrentFilter"]"
class="btn btn-default @prevDisabled">
上一页
</a>
<a asp-action="Index"
asp-route-sortOrder="@ViewData["CurrentSort"]"
asp-route-pageNumber="@(Model.PageIndex + 1)"
asp-route-currentFilter="@ViewData["CurrentFilter"]"
class="btn btn-default @nextDisabled">
下一页
</a>
(3.5)ChangePass视图代码
https://img2022.cnblogs.com/blog/39139/202211/39139-20221119164729484-1910965122.jpg
@model ChangePassView
@section Scripts{
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
<form action="/Manager/ChangePass" method="post">
@Html.AntiForgeryToken()
<label asp-for="OldPass">旧密码</label>
<input type="hidden" asp-for="Id" />
<input type="password" asp-for="OldPass" name="OldPass" placeholder="密码" />
<span asp-validation-for="OldPass" class="text-danger"></span>
<label asp-for="NewPass">新密码</label>
<input type="password" asp-for="NewPass" name="NewPass" placeholder="密码" />
<span asp-validation-for="NewPass" class="text-danger"></span>
<label asp-for="ConfirmNewPass">确认新密码</label>
<input type="password" asp-for="ConfirmNewPass" name="ConfirmNewPass" placeholder="确认密码" />
<span asp-validation-for="ConfirmNewPass" class="text-danger"></span>
<button type="submit">确定</button>
<button type="reset">重置</button>
</form>
(3.6)ChangeRole视图代码
https://img2022.cnblogs.com/blog/39139/202211/39139-20221119164729190-1756328859.jpg
@using RjWebCms.Models;
@{ ViewData["Title"] = "修改对应角色"; }
@model ChangeUserRole
<form action="/Manager/ChangeRole" method="post">
@Html.AntiForgeryToken()
<label asp-for="Id">选择对应角色</label>
<input type="hidden" asp-for="Id" />
@Html.DropDownList("ddl_RoleList", ViewBag.database as IEnumerable<SelectListItem>)
<button type="submit">确定</button>
<button type="reset">重置</button>
</form>
(4).用户Controller部分的实现
public class ManagerController : Controller{
private readonly IManagerService _manager;
private readonly IManagerRoleService _managerRoleService;
private readonly AppDbContext _appDbContext;
public ManagerController(IManagerService manager,IManagerRoleService managerRoleService, AppDbContext appDbContext){
_manager = manager;
_managerRoleService = managerRoleService;
_appDbContext = appDbContext;
}
public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? pageNumber){
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}
#region 分页操作数据
ViewData["CurrentFilter"] = searchString;
var managers = from s in _appDbContext.Manager
join t in _appDbContext.ManagerRole on s.RoleId equals t.Id
select new PageManager{
Id=s.Id,
RoleId =s.RoleId,
UserName = s.UserName,
Email = s.Email,
Mobile = s.Mobile,
AddTime = s.AddTime,
RoleName = t.RoleName};
if (!string.IsNullOrEmpty(searchString))
{
managers = managers.Where(s => s.UserName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
managers = managers.OrderByDescending(s => s.UserName);
break;
case "Date":
managers = managers.OrderBy(s => s.AddTime);
break;
case "date_desc":
managers = managers.OrderByDescending(s => s.AddTime);
break;
default:
managers = managers.OrderBy(s => s.UserName);
break;
}
#endregion
int pageSize = 4;
return View(await PaginatedList<PageManager>.CreateAsync(managers.AsNoTracking(), pageNumber ?? 1, pageSize));
}
public IActionResult Create()
{
return View();
}
public async Task<IActionResult> Create(RegisterManagerView manager)
{
if (ModelState.IsValid)
{
Manager mUser = new Manager
{
UserName = manager.UserName,//但暂时用重写的方式来处理
Password = AESEncryptHelper.Encode(manager.Password.Trim(), RjWebKeys.AesEncryptKeys), //对密码加密;
Mobile = manager.Mobile,
Email = manager.Email,
Remark = manager.Remark
};
//此处可以用AutoMapper进行转换
//因为AddManagerAsync的参数是Manager对象,而非RegisterManagerView对象
//否则就需要重写一个AddManagerAsync(RegisterManagerView manager) 这样的方法
var successful = await _manager.AddManagerAsync(mUser);
if (successful)
return RedirectToAction("Index");
else
return BadRequest("失败");
}
return View(manager);
}
public async Task<IActionResult> Edit(int id)
{
if (string.IsNullOrEmpty(id.ToString()))
return NotFound();
var m = await _manager.FindManagerAsync(id);
if (m == null)
return NotFound();
EditManagerView mView = new EditManagerView() {
Id = id,
UserName = m.UserName,
//Password = AESEncryptHelper.Decode(m.Password,RjWebKeys.AesEncryptKeys), //解密密码
//ConfirmPassword = AESEncryptHelper.Decode(m.Password, RjWebKeys.AesEncryptKeys), //解密密码
Mobile = m.Mobile,
Email = m.Email,
Remark = m.Remark
};
return View(mView);
}
public async Task<IActionResult> Edit(int id, EditManagerView editManager)
{
if (string.IsNullOrEmpty(id.ToString()))
return NotFound();
if (ModelState.IsValid)
{
try
{
//做个对象转换
Manager mUser = new Manager {
UserName = editManager.UserName,
Mobile = editManager.Mobile,
Email = editManager.Email,
Remark = editManager.Remark
};
//因为UpdateManagerAysnc方法参数为完整Manger对象,所以要转换
var result = await _manager.UpdateManagerAysnc(id, mUser);
if(result)
return RedirectToAction("Index");
else
return BadRequest("编辑失败");
}
catch (Exception ex)
{
return BadRequest("编辑失败");
}
}
return View();
}
public async Task<IActionResult> Details(int id)
{
var item = await _manager.FindManagerAsync(id);
return View(item);
}
public async Task<IActionResult> Delete(int id)
{
var result = await _manager.DeleteManagerAsync(id);
if (result)
return RedirectToAction("Index");
else
return Ok("删除失败!");
}
public async Task<IActionResult> ChangePass(int id)
{
if (string.IsNullOrEmpty(id.ToString()))
return NotFound();
//密码框的初始化也可以省略
var m = await _manager.FindManagerAsync(id);
if (m == null)
return NotFound();
ChangePassView cpView = new ChangePassView {
Id=id,
OldPass = AESEncryptHelper.Decode(m.Password, RjWebKeys.AesEncryptKeys) //解密密码m.Password,
};
return View(cpView);
}
public async Task<IActionResult> ChangePass(int id,ChangePassView cheView)
{
if (string.IsNullOrEmpty(id.ToString()))
return NotFound();
if (ModelState.IsValid)
{
//ChangePass方法在ManagerService中,注意参数对象
var successful = await _manager.ChangePass(id,cheView);
if (successful)
return RedirectToAction("Index");
else
return BadRequest("失败");
}
return View();
}
public async Task<IActionResult> ChangeRole(int id)
{
//本Action调用后,要初始化下拉框的选择
var user = await _manager.FindManagerAsync(id);
if (user == null)
return NotFound();
#region 绑定类别下拉框
var rolelist = await _managerRoleService.GetManagerRoleAsync();
var roleItems = new List<SelectListItem>()
{
new SelectListItem(){ Value="0",Text="全部",Selected=true}
};
foreach (var role in rolelist)
{
SelectListItem item = new SelectListItem() { Value = role.Id.ToString(), Text = role.RoleName };
roleItems.Add(item);
}
//遍历并选中(实现选中下拉框功能)
foreach (SelectListItem item in roleItems)
{
if (item.Value == user.RoleId.ToString())
item.Selected = true;
}
ViewBag.database = roleItems;
#endregion
return View();
}
public async Task<IActionResult> ChangeRole(int id ,ChangeUserRole user)
{
//修改用户所属角色
if (string.IsNullOrEmpty(id.ToString()))
return NotFound();
#region 取下拉菜单值(RoleId)
string strRoleId = Request.Form["ddl_RoleList"];
if (!string.IsNullOrEmpty(strRoleId))
user.RoleId = int.Parse(strRoleId);
else
user.RoleId = 0;
#endregion
if (ModelState.IsValid)
{
try
{
//ChangeRole方法在ManagerService中,注意其参数
var result = await _manager.ChangeRole(id, user);
if (result)
return RedirectToAction("Index");
else
return BadRequest("编辑失败");
}
catch (Exception ex)
{
return BadRequest("编辑失败");
}
}
return View();
}
#region 验证功能
public async Task<IActionResult> CheckUserName(string UserName)
{
//result=true,表示有这个用户名,说明验证失败,无法添加
//那么return json 需要返回一个false
bool result = await _manager.CheckUserName(UserName);
return Json(!result); //返回结果必须是Json格式
}
public async Task<IActionResult> CheckMobile(string Mobile)
{
//result=true,表示有这个手机号,说明验证失败,无法添加
//那么return json 需要返回一个false
bool result = await _manager.CheckMobile(Mobile);
return Json(!result); //返回结果必须是Json格式
}
public async Task<IActionResult> CheckEmail(string Email)
{
//result=true,表示有这个邮箱,说明验证失败,无法添加
//那么return json 需要返回一个false
bool result = await _manager.CheckEmail(Email);
return Json(!result); //返回结果必须是Json格式
}
public async Task<IActionResult> CheckOldPass(int id,string oldpass)
{
//result=true,表示有这个旧密码,说明验证失败,无法添加
//那么return json 需要返回一个false
string strPass = AESEncryptHelper.Encode(oldpass.Trim(), RjWebKeys.AesEncryptKeys); //对密码加密;
bool result = await _manager.CheckOldPass(id,strPass);
return Json(result); //返回结果必须是Json格式
}
#endregion
}
2.用户分配角色
分配角色在ChangeRole视图页面完成,注意阅读其对应代码;
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]