这节我们主要演示在ASP.NET Core Identity中创建、修改、删除、查询用户
1、ASP.NET Core Identity UserManager 类
方法名称 | 描述 |
FindByIdAsync(id) | 根据指定的ID查询用户对象 |
CreateAsync(user,password) | 注册一个新的用户 |
UpdateAsync(user) | 修改一个已经存在的用户 |
DeleteAsync(user) | 移除一个指定的用户 |
AddToRoleAsync(user, name) | 给用户添加角色 |
RemoveFromRoleAsync(user, name) | 从角色中移除用户 |
GetRolesAsync(user) | 获取角色名字列表 |
IsInRoleAsync(user, name) | 返回一个标志,表示是否是给与角色名字的成员 |
表格中显示AppUser类常用的属性
名称 | 描述 |
Id | 包含用户唯一ID |
UserName | 包含用户名称 |
包含用户Email |
2、创建Identity 用户
我们在Models文件创建一个User.cs的类,该类中有三个公共属性Name,Email & Password,类型都是字符串,我们给每个属性都加上 [Required]特性。
为了验证正确的Email输入,在Email属性上加上正则表达式验证(RegularExpression)
public class User{[Required][DisplayName("用户名")]public string Name { get; set; } = null!;[Required][DisplayName("邮箱")][RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "电子邮件格式不正确")]public string Email { get; set; } = null!;[Required][DataType(DataType.Password)][DisplayName("密码")]public string Password { get; set; } = null!;}
在Controllers文件夹下新增一个新的AdminController类,在该控制器中创建CURD方法,AdminController如下:
public class AdminController : Controller{private UserManager<AppUser> _userManager;public AdminController(UserManager<AppUser> userManager){_userManager = userManager;}public IActionResult Index(){return View();}}
在AdminController的构造函数中引用UserManager类,接下来我们添加Create方法来创建新用户,如下代码:
public ViewResult Create()=>View();[HttpPost]public async Task<IActionResult> Create(User user){if (ModelState.IsValid){AppUser appUser = new AppUser{UserName = user.Name,Email = user.Email,};var identityResult = await _userManager.CreateAsync(appUser, user.Password);if (identityResult.Succeeded)return RedirectToAction("Index", "Admin");elseforeach (IdentityError error in identityResult.Errors)ModelState.AddModelError("", error.Description);}return View(user);}
Post版本的Create方法创建一个新的Identity用户,该方法的参数获取一个User类并检查模型绑定是否成功。如果模型绑定成功创建一个AppUser类的实例并且将UserName和Email赋值给该对象
AppUser appUser = new AppUser{UserName = user.UserName,Email = user.Email,};
var identityResult = await _userManager.CreateAsync(appUser, user.Password);if (identityResult.Succeeded){return RedirectToAction("Index", "Admin");}else{foreach (IdentityError error in identityResult.Errors){ModelState.AddModelError("", error.Description);}}
接下来我们在视图文件Views->Admin文件加下创建一个Create.cshtml,代码如下:
@model User@{ViewData["Title"] = "新增用户";}<div asp-validation-summary="All" class="text-danger"></div><form class="form-horizontal" role="form" method="post"><div class="mb-3 row"><label asp-for="Name" class="col-sm-1 control-label"></label><div class="col-sm-11"><input asp-for="Name" class="form-control" /></div></div><div class="mb-3 row"><label asp-for="Email" class="col-sm-1 control-label"></label><div class="col-sm-11"><input asp-for="Email" class="form-control" /></div></div><div class="mb-3 row"><label asp-for="Password" class="col-sm-1 control-label"></label><div class="col-sm-11"><input asp-for="Password" class="form-control" /></div></div><div class="mb-3 row"><div class="col-sm-11 offset-sm-1"><button type="submit" class="btn btn-primary">保存</button><button asp-action="Index" class="btn btn-secondary">返回</button></div></div></form>
用户可以通过该表单将用户名&邮件&密码提交AdminControlle的Create方法,从而保存到数据库中

输入下面信息并点击确认:
姓名: Yogi
邮箱: yogi@gmail.com
密码: Admin@123
每次创建完用户之后都会跳转到Index 视图,该视图展示了数据库中所有的用户信息。接下来我们创建显示用户列表的页面
我们创建所有Identity用户存储到AspNetUsers表,打开这个表发现用户记录已经被创建。出于安全目的,ASP.NET Core Identity将我们密码进行加密存储,并不是存储的平面文本:

roller的Index方法:
public class AdminController : Controller{private UserManager<AppUser> _userManager;public AdminController(UserManager<AppUser> userManager){_userManager = userManager;}public IActionResult Index(){return View(_userManager.Users);}}
我们将所有的用户以IEnumerable形式返回到View。
@model IEnumerable<AppUser>@{ViewData["Title"] = "用户列表";}<div class="container"><div class="row mb-3"><div class="col-sm-3"><a asp-action="Create" class="btn btn-primary">新增</a></div><div class="col-sm-3"></div><div class="col-sm-3"></div><div class="col-sm-3"></div></div><div class="row mb-3"><div class="col-sm"><table class="table table-bordered align-middle"><thead><tr><th>编号</th><th>名称</th><th>邮件</th></tr></thead><tbody>@foreach (AppUser user in Model){<tr><td>@user.Id</td><td>@user.UserName</td><td>@user.Email</td></tr>}</tbody></table></div></div></div>
在这个View中接受一个IEnumerable<AppUser>的模型类,使用foreach循环该类将所有用户的信息显示在表格内
Admin ,将调用Index方法。下面图中显示了在数据库中的所有的用户记录:

4、更新用户记录
@model IEnumerable<AppUser>@{ViewData["Title"] = "用户列表";}<div class="container"><div class="row mb-3"><div class="col-sm-3"><a asp-action="Create" class="btn btn-primary">新增</a></div><div class="col-sm-3"></div><div class="col-sm-3"></div><div class="col-sm-3"></div></div><div class="row mb-3"><div class="col-sm"><table class="table table-bordered align-middle"><thead><tr><th>编号</th><th>名称</th><th>邮件</th><th>编辑</th></tr></thead><tbody>@foreach (AppUser user in Model){<tr><td>@user.Id</td><td>@user.UserName</td><td>@user.Email</td><td><a class="btn btn-primary btn-sm" asp-action="Update" asp-route-id="@user.Id">编辑</a></td></tr>}</tbody></table></div></div></div>
我们修改一下AdminController:
public class AdminController : Controller{private UserManager<AppUser> _userManager;private IPasswordHasher<AppUser> _passwordHasher;public AdminController(UserManager<AppUser> userManager,IPasswordHasher<AppUser> passwordHash){_userManager = userManager;_passwordHasher = passwordHash;}}
public async Task<IActionResult> Update(string Id){var appUser = await _userManager.FindByIdAsync(Id);if (appUser != null){var updateUserDTO = new UpdateUserDTO();updateUserDTO.Id = appUser.Id;updateUserDTO.Name = appUser.UserName ?? "";updateUserDTO.Email = appUser.Email == null ? "" : appUser.Email;return View(updateUserDTO);}else{return RedirectToAction("Index");}}[HttpPost]public async Task<IActionResult> Update(UpdateUserDTO updateUserDTO){var appUser = await _userManager.FindByIdAsync(updateUserDTO.Id);if (appUser != null){if (updateUserDTO.Email != null)appUser.Email = updateUserDTO.Email;elseModelState.AddModelError("", "邮箱不能为空");if (updateUserDTO.Name != null)appUser.UserName = updateUserDTO.Name;elseModelState.AddModelError("", "用户名不能为空");if (updateUserDTO.Password != null)appUser.PasswordHash = _passwordHasher.HashPassword(appUser, updateUserDTO.Password);elseModelState.AddModelError("", "密码不能为空");if (!string.IsNullOrEmpty(updateUserDTO.Email) &&!string.IsNullOrEmpty(updateUserDTO.Password)){var result = await _userManager.UpdateAsync(appUser);if (result.Succeeded)return RedirectToAction("Index");else{foreach (IdentityError error in result.Errors){ModelState.AddModelError("", error.Description);}}}}elseModelState.AddModelError("", "没有发现该用户");return View(updateUserDTO);}
HTTP GET版本的Update方法参数接受一个字符串类型的Id。这个Id表示用户注册时生成的Id,用UserManager类FindByIdAsync()方法从Identity数据库中查找该用户记录,该方法提供了通过用户Id查找用户信息
var appUser = await _userManager.FindByIdAsync(Id); var appUser = await _userManager.FindByIdAsync(Id);如果AppUser对象不是null,我们检查email和password是否为null,如果不为null我们更新AppUser类Email和PasswordHash属性值,我们将修改后的AppUser作为参数传递给UserManager类的UpdateAsync方法
if (updateUserDTO.Email != null)appUser.Email = updateUserDTO.Email;elseModelState.AddModelError("", "邮箱不能为空");if (updateUserDTO.Password != null)appUser.PasswordHash = _passwordHasher.HashPassword(appUser, updateUserDTO.Password);elseModelState.AddModelError("", "密码不能为空");
appUser.PasswordHash = _passwordHasher.HashPassword(appUser, updateUserDTO.Password);var result = await _userManager.UpdateAsync(appUser);if (result.Succeeded)return RedirectToAction("Index");elseforeach (IdentityError error in result.Errors)Errors(error);
void Errors(IdentityResult result){foreach (IdentityError error in result.Errors)ModelState.AddModelError("", error.Description);}
@model UpdateUserDTO@{ViewData["Title"] = "修改用户";}<div asp-validation-summary="All" class="text-danger"></div><form class="form" method="post" role="form"><div class="row mb-3"><label asp-for="Id" class="col-sm-1 control-label"></label><div class="col-sm-11"><input asp-for="Id" class="form-control" disabled /></div></div><div class="mb-3 row"><label asp-for="Name" class="col-sm-1 control-label"></label><div class="col-sm-11"><input asp-for="Name" class="form-control" /></div></div><div class="row mb-3"><label asp-for="Email" class="col-sm-1 form-label"></label><div class="col-sm-11"><input asp-for="Email" class="form-control" /></div></div><div class="row mb-3"><label asp-for="Password" class="col-sm-1 form-label"></label><div class="col-sm-11"><input asp-for="Password" class="form-control" /></div></div><div class="row mb-3"><div class="col-sm-11 offset-sm-1"><button class="btn btn-primary">保存</button><button asp-action="index" class="btn btn-secondary">返回</button></div></div></form>
public class UpdateUserDTO{[Required][DisplayName("编号")]public string Id { get; set; } = null!;[Required][DisplayName("用户名")]public string Name { get; set; }=null!;[Required][DisplayName("邮箱")][RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "E-mail is not valid")]public string Email { get; set; } = null!;[Required][DataType(DataType.Password)][DisplayName("密码")]public string Password { get; set; } = null!;}



最后我们完成删除操作。使用AdminControoler中的Delete方法完成。代码如下:
[HttpPost]public async Task<IActionResult> Delete(string Id){var appUser = await _userManager.FindByIdAsync(Id);if (appUser != null){var result = await _userManager.DeleteAsync(appUser);if (result.Succeeded)return RedirectToAction("Index");elseErrors(result);}elseModelState.AddModelError("", "没有发现该用户");return View("Index", _userManager.Users);}
var result = await _userManager.DeleteAsync(appUser);如果删除成功,用户会跳转到Index方法,否则会将相应的错误显示到浏览器
我们在Index.cshtml页面添加删除按钮。代码如下:
@model IEnumerable<AppUser>@{ViewData["Title"] = "用户列表";}<div class="container"><div class="row mb-3"><div class="col-sm-3"><a asp-action="Create" class="btn btn-primary">新增</a></div><div class="col-sm-3"></div><div class="col-sm-3"></div><div class="col-sm-3"></div></div><div class="row mb-3"><div class="col-sm"><table class="table table-bordered align-middle"><thead><tr><th>编号</th><th>名称</th><th>邮件</th><th>编辑</th><th>删除</th></tr></thead><tbody>@foreach (AppUser user in Model){<tr><td>@user.Id</td><td>@user.UserName</td><td>@user.Email</td><td><a class="btn btn-primary btn-sm" asp-action="Update" asp-route-id="@user.Id">编辑</a></td><td><form method="post" asp-action="Delete" asp-route-id="@user.Id" role="form"><button type="submit" class="btn btn-danger btn-sm">删除</button></form></td></tr>}</tbody></table></div></div></div>


总结
这节我们主要介绍了在ASP.NET Core Identity中新增、查询、修改、删除用户,在下一节我们将针对用户名、邮箱、密码创建策略,以及客户自定义规则
源代码地址:
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/AspNetCore.Identity/Identity