前言:
本系列文章主要為我之前所學知識的一次微小的實踐,以我學校圖書館管理系統為雛形所作。
本系列文章主要參考資料:
微軟文檔: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
修改前地址:https://github.com/NanaseRuri/LibraryDemo/tree/SomeError
本章內容: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>
結果: