學習ASP.NET Core Razor 編程系列目錄
學習ASP.NET Core Razor 編程系列二——添加一個實體
學習ASP.NET Core Razor 編程系列三——創建數據表及創建項目基本頁面
學習ASP.NET Core Razor 編程系列四——Asp.Net Core Razor列表模板頁面
學習ASP.NET Core Razor 編程系列五——Asp.Net Core Razor新建模板頁面
學習ASP.NET Core Razor 編程系列六——數據庫初始化
學習ASP.NET Core Razor 編程系列七——修改列表頁面
並發異常處理
在Visual Studio 2017的解決方案資源管理器中找到 Pages/Books/Edit.cshtml.cs 文件,鼠標雙擊打開 ,在代碼中找到OnPostAsync方法。並按如下代碼進行修改:
public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } _context.Attach(Book).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!_context.Book.Any(e => e.ID == Book.ID)) { return NotFound(); } else { throw; } } return RedirectToPage("./Index"); }
上面的代碼功能是當檢測到第一個客戶端在刪除書籍信息時,第二個客戶端對要刪除的書籍信息進行修改並保存時發生異常。
我們可以進行以下操作來重現上面的異常。
- 在 catch (DbUpdateConcurrencyException) 上設置斷點。如下圖。

2. 在Visual Studio 2017中按F5,運行應用程序,在打開的瀏覽器的一個窗口中,選擇一本書籍進行修改。如下圖。
3. 在另一個瀏覽器窗口中,選擇同一本書籍信息的“Delete”鏈接,然后刪除此書籍。
4. 在編輯書籍信息的瀏覽器窗口中,將書籍信息的修改內容保存到數據庫。如下圖。

5. 當兩個或更多客戶端同時更新記錄時,代碼通常將檢測到並發沖突。如下圖。

GET請求與POST請求
接下來我們根據 Pages/Books/Edit.cshtml.cs 文件內容來介紹一下請求過程,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; using RazorMvcBooks.Models; namespace RazorMvcBooks.Pages.Books { public class EditModel : PageModel { private readonly RazorMvcBooks.Models.BookContext _context; public EditModel(RazorMvcBooks.Models.BookContext context) { _context = context; } [BindProperty] public Book Book { get; set; } public async Task<IActionResult> OnGetAsync(int? id) { if (id == null) { return NotFound(); } Book = await _context.Book.SingleOrDefaultAsync(m => m.ID == id); if (Book == null) { return NotFound(); } return Page(); } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } _context.Attach(Book).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!_context.Book.Any(e => e.ID == Book.ID)) { return NotFound(); } else { throw; } } return RedirectToPage("./Index"); } } }
1. 當瀏覽器對Books/Edit 頁面發出 HTTP GET 請求時(例如 http://localhost:5000/Books/Edit/9):
- OnGetAsync 方法從數據庫提取書籍信息並把數據傳遞給Page 方法。
- Page 方法呈現“Pages/Books/Edit.cshtml”Razor 頁面。 Pages/Books/Edit.cshtml 文件包含實體指令 (@model RazorMvcBooks.Pages.Books.EditModel),這使書籍實體在頁面上可用。
- 頁面中的表單會顯示書籍實體中的值。
2. 當瀏覽器對Books/Edit 頁面發出Post請求時:
- 此頁面上的表單值將綁定到 Book 屬性上。 [BindProperty] 特性會啟用實體屬性綁定。具體代碼參見上面的代碼。
- 如果實體對象的屬性值中存在錯誤(例如,ReleaseDate 無法被轉換為日期),則會使用已提交的值再次請求表單。
- 如果實體對象的屬性值中沒有錯誤,則把書籍信息保存到數據庫。
“Index.cshtml”、“Create.cshtml”和“delete.cshtml”Razor 頁面中的 HTTP GET 方法的實現原理與上面所述的Get請求類似。 “Create.cshtml”Razor 頁面中的 POST請求方法的實現原理與上面所述的POST請求類似。
