參照VS自帶的基架(Scaffold)系統-MVC Controller with views, using Entity Framework我們來建立CRUD方法。
① 将上一篇的Models/UserContext.cs檔案中的用來指定使用的資料庫邏輯的<code>OnConfiguring</code>方法删除,将邏輯移到Startup.cs檔案中的<code>ConfigureServices</code>方法中。
② 在UserController.cs 構造函數中采用依賴注入來注入一個資料庫上下文到該控制器。資料庫上下文将被應用到控制器中的每一個CRUD方法。
③ 在UserController.cs中添加基本的CRUD方法:
一個<code>http://localhost:5000/User</code> 這樣的請求到達User控制器後,将會從<code>User</code>表傳回所有的資料,将将這些資料傳遞到<code>Index</code>視圖:
④ 在Views/User檔案夾中添加與上述Action方法名稱相對應的Index.cshtml檔案、Create.cshtml檔案、Details.cshtml檔案、Edit.cshtml檔案、Delete.cshtml檔案。
Create.cshtml運作效果:
Details.cshtml運作效果:
Edit.cshtml運作效果:
Delete.cshtml運作效果:
MVC提供了傳遞強類型對象給視圖的能力,這樣為你的代碼提供了更好的編譯時檢查,并在VS中提供了更豐富的智能感覺功能。
檢視UserController/Details方法:
<code>id</code>參數通常作為路由資料來傳遞,比如 <code>http://localhost:5000/user/details/1</code> 會:
Controller設定為<code>user</code>(第一個URL段)
Action設定為<code>details</code>(第二個URL段)
id設定為1(第三個URL段)
你也可以通過查詢字元串來傳遞<code>id</code>:
<code>http://localhost:5000/user/details?id=1</code>
如果指定的User被找到,則<code>User</code> Model執行個體将被傳遞到<code>Details</code>視圖:
檢視Views/User/Details.cshtml檔案:
你會發現在頂部有一個<code>@model</code>語句,你可以指定視圖所期望的對象類型。
<code>@model</code>指令允許你通過使用強類型的<code>Model</code>對象來通路從控制器傳遞到視圖的User對象。例如,在Details.cshtml視圖中,通過使用強類型的<code>Model</code>對象傳遞User的每一個字段到<code>DisplayNameFor</code>和<code>DisplayFor</code> HTML Helper。
再來檢視Index.cshtml檔案和User控制器中的<code>Index</code>方法。注意在調用View方法時,是如何建立一個<code>List</code>對象的。下面的代碼将從<code>Index</code> Action方法傳遞整個<code>User</code>到視圖中。
User控制器中的<code>Index</code>方法:
Index.cshtml檔案最頂部:
<code>@model</code>指令允許你通路通過強類型的<code>Model</code>從控制器傳遞到視圖的User清單。例如,在Index.cshtml視圖中,在強類型的<code>Model</code>對象上通過<code>foreach</code>語句周遊了整個User清單:
首先,建立一個Repositories檔案夾。在該檔案夾下定義一個<code>IUserRepository</code>接口。
接着再添加一個<code>UserRepository</code>來實作<code>IUserRepository</code>接口。将之前定義的UserContext.cs邏輯移到該類中,在UserRepository.cs 構造函數中采用依賴注入來注入一個資料庫上下文(UserContext)到該倉儲類。資料庫上下文将被應用到倉儲類中的每一個CRUD方法。
再修改Controllers/UserController.cs檔案,将<code>private readonly</code>的<code>UserContext</code>變量删除:
private readonly UserContext _context;
添加<code>IUserRepository</code>變量:
将所有方法中的<code>_context</code>操作删除,替換成<code>_userRepository</code>。例如,将<code>Index</code>方法中的<code>_context.Users.ToListAsync()</code>删除:
return View(await _context.Users.ToListAsync());
替換成
最終的UserController.cs如下:
通過定義Repository接口,從MVC Controller中解耦該repository類。通過注入一個UserRepository來代替直接在Controller裡面執行個體化一個UserRepository類。
為了注入一個Repository到Controller,我們必須通過DI容器來注冊它,打開Startup.cs檔案,在ConfigureServices方法添加如下代碼:
我們為Models/User.cs檔案添加<code>Display</code>和<code>DataType</code>注解,首先要添加必要的命名空間<code>using System.ComponentModel.DataAnnotations;</code>:
再将屬性在視圖上顯示成中文:
<code>Display</code> Attribute指定字段的顯示名,<code>DataType</code>Attribute指定資料類型。
最終的顯示效果如下:
打開Views/User/Index.cshtml,你會發現Edit,Details,Delete連結是由MVC Core Anchor Tag Helper生成的。
Tag Helpers允許伺服器代碼在Razor檔案中參與建立和渲染HTML元素。在上述代碼中,<code>AnchorTagHelper</code>從Controller Action動作方法和路由ID動态生成HTML<code>href</code>屬性值。
檢視Startup.cs中的<code>Configure</code>方法:
ASP.NET Core會将<code>http://localhost:5000/User/Edit/4</code> 轉換成發送給<code>User</code>控制器的<code>Edit</code>方法(帶有值為4的<code>Id</code>參數)的請求。
檢視UserController.cs中的<code>[HttpPost]</code>版本的<code>Edit</code>方法:
<code>[Bind]</code> Attribute是一種防止over-posting(過度送出)的方式。應該隻把你需要改變的屬性包含到<code>[Bind]</code> Attribute中。
<code>[ValidateAntiForgeryToken]</code> Attribute是用來防止僞造請求的,會與Views/User/Edit.cshtml視圖檔案生成的反僞造标記(Token)進行配對。Views/User/Edit.cshtml視圖檔案通過Form Tag Helper來生成反僞造标記(Token)。
Form Tag Helper生成一個隐藏的防僞标記必須和<code>User</code>控制器中的<code>Eidt</code>方法的<code>[ValidateAntiForgeryToken]</code>産生的防僞标記相比對。
檢視Edit.cshtml,會發現基架系統(Scaffolding System)會為<code>User</code>類的每一個屬性生成用來呈現的<code><label></code>和<code><input></code>元素。
基架代碼使用了多個Tag Helper方法來簡化HTML标記。
Label Tag Helper用來顯示字段的名字。
Input Tag Helper用來呈現HTML<code><input></code>元素。
Validation Tag Helper用來顯示關聯屬性的驗證資訊。
最終在浏覽器中為<code><form></code>元素所生成的HTML如下:
HTML<code><form></code>中的<code>action</code>Attribute設定成POST到<code>/User/Edit/id</code>URL(所有<code><input></code>元素都在該<code><form></code>元素中)。當點選<code>Save</code>按鈕時,表單資料會被發送(POST)到伺服器。在<code></form></code>元素的上面顯示了Form Tag Helper所生成的隐藏的XSRF反僞造标記。
檢視<code>[HttpPost]</code>版本的Edit方法:
<code>[ValidateAntiForgeryToken]</code>驗證Form Tag Helper中的反僞造标記生成器所生成的隐藏的XSRF反僞造标記。
模型綁定(Model Binding)機制接受POST過來的表單資料并建立一個<code>User</code>對象并作為<code>user</code>參數。<code>ModelState.IsValid</code>方法驗證從表單送出過來的資料可以用來修改一個<code>User</code>對象。如果資料有效,就可以進行儲存。被更新的資料通過調用資料庫的上下文(Database Context)的<code>SaveChangesAsync</code>方法來儲存到資料庫中。資料儲存之後,代碼将使用者重定向到<code>UserController</code>類的<code>Index</code>方法。該頁面會顯示剛剛被改動後的最新的使用者集合。
在表單被POST到伺服器之前,用戶端驗證會檢查所有字段上的驗證規則,如果有任何驗證錯誤,則會顯示該錯誤資訊,并且表單不會被發送到伺服器。如果禁用了JS,将不會有用戶端驗證,但伺服器會檢測POST過來的資料是無效的,表單會重新顯示錯誤資訊。
Adding a model
over-posting
我的個人部落格