天天看點

建立ASP.NET Core MVC應用程式(4)-添加CRUD動作方法和視圖

參照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>&lt;label&gt;</code>和<code>&lt;input&gt;</code>元素。

基架代碼使用了多個Tag Helper方法來簡化HTML标記。

Label Tag Helper用來顯示字段的名字。

Input Tag Helper用來呈現HTML<code>&lt;input&gt;</code>元素。

Validation Tag Helper用來顯示關聯屬性的驗證資訊。

最終在浏覽器中為<code>&lt;form&gt;</code>元素所生成的HTML如下:

HTML<code>&lt;form&gt;</code>中的<code>action</code>Attribute設定成POST到<code>/User/Edit/id</code>URL(所有<code>&lt;input&gt;</code>元素都在該<code>&lt;form&gt;</code>元素中)。當點選<code>Save</code>按鈕時,表單資料會被發送(POST)到伺服器。在<code>&lt;/form&gt;</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

我的個人部落格