前言:
本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作。
本系列文章主要参考资料:
微软文档:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windows
《Pro ASP.NET MVC 5》、《锋利的 jQuery》
此系列皆使用 VS2017+C# 作为开发环境。如果有什么问题或者意见欢迎在留言区进行留言。
项目 github 地址:https://github.com/NanaseRuri/LibraryDemo
本章内容:Ajax 提交自定义对象、Ajax 提交数组
此处全部都在 /AdminAccount/Index 页面完成。
一、学生信息编辑首页
创建一个 Admin 控制器用于编辑学生信息:
1 [Authorize(Roles = "Admin")] 2 public class AdminAccountController : Controller 3 { 4 private UserManager<Student> _userManager; 5 6 public AdminAccountController(UserManager<Student> userManager) 7 { 8 _userManager = userManager; 9 } 10 11 public IActionResult Index() 12 { 13 ICollection<Student> students = _userManager.Users.ToList(); 14 return View(students); 15 } 16 }
视图:
@using LibraryDemo.Models.DomainModels @model IEnumerable<LibraryDemo.Models.DomainModels.Student> @{ ViewData["Title"] = "AccountInfo"; Student stu = new Student(); } <link rel="stylesheet" href="~/css/BookInfo.css" /> <h2>学生信息</h2> <div id="buttonGroup"> <button class="btn btn-primary" onclick="return addStudent()">添加学生</button> <button class="btn btn-danger" onclick="return confirmDelete()">删除学生</button> </div> <br /> <table> <thead> <tr> <th></th> <th>@Html.LabelFor(m => stu.UserName)</th> <th>@Html.LabelFor(m => stu.Name)</th> <th>@Html.LabelFor(m => stu.Degree)</th> <th>@Html.LabelFor(m => stu.PhoneNumber)</th> <th>@Html.LabelFor(m => stu.Email)</th> <th>@Html.LabelFor(m => stu.MaxBooksNumber)</th> </tr> </thead> <tbody id="studentList"> @if (!@Model.Any()) { <tr><td colspan="6">未有学生信息</td></tr> } else { foreach (var student in Model) { <tr> <td><input type="checkbox" name="userNames" value="@student.UserName" /></td> <td>@student.UserName</td> <td>@student.Name</td> <td>@Html.DisplayFor(m => student.Degree)</td> <td>@student.PhoneNumber</td> <td>@student.Email</td> <td>@student.MaxBooksNumber</td> </tr> } } </tbody> </table>
结果:
二、增加新学生
此处打算使用 Ajax 来实现无刷新页面更新,因此动作方法返回类型为 Json 。
动作方法:
此处需注意在参数处添加 [FromBody] 修饰,否则无法读取来自页面的数据。
为节省带宽,此处仅返回添加的学生的 JSON 。
1 [HttpPost] 2 public async Task<JsonResult> AddStudent([FromBody]Student student) 3 { 4 if (_userManager.CreateAsync(student,"123456").Result.Succeeded) 5 { 6 return await AddedStudent(student.UserName); 7 } 8 9 return Json("Failed"); 10 } 11 12 public async Task<JsonResult> AddedStudent(string userName) 13 { 14 Student student=await _userManager.Users.FirstOrDefaultAsync(s => s.UserName == userName); 15 return Json(new 16 { 17 userName = student.UserName, 18 name = student.Name, 19 degree = student.Degree == Degrees.CollegeStudent ? "本科生" : (student.Degree == Degrees.Postgraduate ? "研究生" : "博士生"), 20 phoneNumber = student.PhoneNumber, 21 email = student.Email, 22 maxBooksNumber = student.MaxBooksNumber 23 }); 24 }
在视图中添加 JS 代码:
此处 JS 代码先是点击 添加书籍 按钮插入一行用于编辑的区域,然后通过插入区域的提交按钮提交信息,在信息成功返回后删除原来进行编辑的行,通过返回的信息添加新的行。
27-33 中由于 ASP.NET Core 后台返回 JSON 数据时会对数据的键的首字母进行小写处理,因此此处读取属性也是使用首字母小写,在后台的键也是使用首字母小写加以强调。
1 <script> 2 function postAddStudent() { 3 $.ajax({ 4 url: "@Url.Action("AddStudent")", 5 contentType: "application/json", 6 method: "POST", 7 data: JSON.stringify({ 8 UserName: $("#UserName").val(), 9 Name: $("#Name").val(), 10 Degree:$("#Degree").val(), 11 PhoneNumber: $("#PhoneNumber").val(), 12 Email: $("#Email").val(), 13 MaxBooksNumber: $("#MaxBooksNumber").val() 14 }), 15 success: function (student) { 16 addStudentToTable(student); 17 } 18 }); 19 } 20 21 function addStudentToTable(student) { 22 var studentList = document.getElementById("studentList"); 23 var studentInfo = document.getElementById("studentInfo"); 24 studentList.removeChild(studentInfo); 25 26 $("#studentList").append(`<tr>` + 27 `<td><input type="checkbox" name="userNames" value="${student.userName}" /></td>` + 28 `<td>${student.userName}</td>` + 29 `<td>${student.name}</td>`+ 30 `<td>${student.degree}</td>` + 31 `<td>${student.phoneNumber}</td>` + 32 `<td>${student.email}</td>` + 33 `<td>${student.maxBooksNumber}</td >` + 34 `</tr>`); 35 } 36 </script>
结果:
三、 批量移除学生
此处亦可以只返回更新过的元素,但为了演示 ASP.NET Core 使用 Ajax 对数组进行处理,故返回新的 Student 列表:
1 [HttpPost] 2 public async Task<JsonResult> RemoveStudent([FromBody]IEnumerable<string> userNames) 3 { 4 Student removedStudent; 5 foreach (var userName in userNames) 6 { 7 removedStudent =await _userManager.FindByNameAsync(userName); 8 if (removedStudent!=null) 9 { 10 await _userManager.DeleteAsync(removedStudent); 11 } 12 } 13 return GetStudentData(); 14 } 15 16 public JsonResult GetStudentData() 17 { 18 var students = _userManager.Users.Select(s =>new 19 { 20 userName=s.UserName, 21 name=s.Name, 22 degree=s.Degree==Degrees.CollegeStudent?"本科生":(s.Degree==Degrees.Postgraduate?"研究生":"博士生"), 23 phoneNumber = s.PhoneNumber, 24 email = s.Email, 25 maxBooksNumber = s.MaxBooksNumber 26 }); 27 return Json(students); 28 }
视图添加 JS 函数:
18 行为数组元素的提交方式,不需像之前一样—— {values:values},否则无法进行数据绑定而导致后台接收到空数据。
为了对表格进行更新,先是通过 jQuery 获取了 tbody 的部分,清空后添加来自后台的新信息:
1 <script> 2 function confirmDelete() { 3 var userNames = document.getElementsByName("userNames"); 4 var message = "确认删除"; 5 var values = []; 6 for (i in userNames) { 7 if (userNames[i].checked) { 8 message = message + userNames[i].value+","; 9 values.push(userNames[i].value); 10 } 11 } 12 message = message + "?"; 13 if (confirm(message)) { 14 $.ajax({ 15 url: "@Url.Action("RemoveStudent")", 16 contentType: "application/json", 17 method: "POST", 18 data: JSON.stringify(values), 19 success: function(students) { 20 updateTable(students); 21 } 22 }); 23 } 24 } 25 26 function updateTable(data) { 27 var body = $("#studentList"); 28 body.empty(); 29 for (var i = 0; i < data.length; i++) { 30 var person = data[i]; 31 body.append(`<tr><td><input type="checkbox" name="userNames" value="${person.userName}" /></td> 32 <td>${person.userName}</td><td>${person.name}</td><td>${person.degree}</td> 33 <td>${person.phoneNumber}</td><td>${person.email}</td><td>${person.maxBooksNumber}</td></tr>`); 34 } 35 }; 36 </script>
结果: