- ASP.NET MVC 教程
- ASP.NET MVC - 首頁
- ASP.NET MVC - 概述
- ASP.NET MVC - 模式
- ASP.NET MVC - 環境設定
- ASP.NET MVC - 入門
- ASP.NET MVC - 生命週期
- ASP.NET MVC - 路由
- ASP.NET MVC - 控制器
- ASP.NET MVC - 操作
- ASP.NET MVC - 過濾器
- ASP.NET MVC - 選擇器
- ASP.NET MVC - 檢視
- ASP.NET MVC - 資料模型
- ASP.NET MVC - 輔助方法
- ASP.NET MVC - 模型繫結
- ASP.NET MVC - 資料庫
- ASP.NET MVC - 驗證
- ASP.NET MVC - 安全性
- ASP.NET MVC - 快取
- ASP.NET MVC - Razor
- ASP.NET MVC - 資料註解
- Nuget 包管理
- ASP.NET MVC - Web API
- ASP.NET MVC - 腳手架
- ASP.NET MVC - Bootstrap
- ASP.NET MVC - 單元測試
- ASP.NET MVC - 部署
- ASP.NET MVC - 自託管
- ASP.NET MVC 有用資源
- ASP.NET MVC 快速指南
- ASP.NET MVC - 有用資源
- ASP.NET MVC - 討論
ASP.NET MVC 快速指南
ASP.NET MVC - 概述
ASP.NET MVC 本質上是微軟的一個Web開發框架,它結合了MVC(模型-檢視-控制器)架構的功能、敏捷開發的最新理念和技術,以及現有ASP.NET平臺的最佳部分。
ASP.NET MVC並非從零開始構建的。它是傳統ASP.NET Web Forms的完整替代方案。它構建在ASP.NET之上,因此開發人員在構建MVC應用程式時可以享受幾乎所有ASP.NET功能。
歷史
ASP.NET 1.0於2002年1月5日作為.Net Framework 1.0版的一部分發布。當時,很容易將ASP.NET和Web Forms視為同一事物。然而,ASP.NET始終支援兩層抽象:
System.Web.UI - Web Forms層,包括伺服器控制元件、ViewState等等。
System.Web - 它提供基本的web棧,包括模組、處理程式、HTTP棧等等。
到2007年ASP.NET MVC釋出時,MVC模式正成為構建Web框架最流行的方式之一。
2009年4月,ASP.NET MVC原始碼在微軟公共許可證(MS-PL)下發布。“ASP.NET MVC框架是一個輕量級、高度可測試的表示框架,它與現有的ASP.NET功能整合在一起。”
其中一些整合功能包括母版頁和基於成員身份的驗證。MVC框架定義在System.Web.Mvc程式集中。
2012年3月,微軟在其web棧(包括ASP.NET MVC、Razor和Web API)的一部分發布了一個開源許可證(Apache License 2.0)。ASP.NET Web Forms未包含在此計劃中。
為什麼選擇ASP.NET MVC?
微軟決定建立他們自己的MVC框架來構建Web應用程式。MVC框架只是構建在ASP.NET之上。當您使用ASP.NET MVC構建Web應用程式時,不會出現狀態錯覺,不會有諸如頁面載入和頁面生命週期之類的事情。
ASP.NET MVC的另一個設計目標是在框架的所有方面都是可擴充套件的。因此,當我們談論檢視時,檢視必須由特定型別的檢視引擎呈現。預設的檢視引擎仍然是可以使用ASPX檔案的引擎。但是,如果您不喜歡使用ASPX檔案,您可以使用其他東西並插入您自己的檢視引擎。
MVC框架內部有一個元件可以例項化您的控制器。您可能不喜歡MVC框架例項化控制器的方式,您可能希望自己處理這項工作。因此,在MVC中有很多地方可以注入您自己的自定義邏輯來處理任務。
使用模型檢視控制器設計模式的整個想法是,您可以保持關注點分離。您的控制器不再受許多與ASP.NET執行時或ASPX頁面的聯絡的限制,這很難進行測試。您現在只需要一個帶有常規方法的類,您可以在單元測試中呼叫它,以瞭解該控制器是否會正確執行。
ASP.NET MVC 的優勢
以下是使用ASP.NET MVC的優勢:
透過將應用程式劃分為模型、檢視和控制器,更容易管理複雜性。
能夠完全控制呈現的HTML,並提供清晰的關注點分離。
直接控制HTML也意味著更好地訪問實現對不斷發展的Web標準的合規性。
方便為現有應用程式新增更多互動性和響應能力。
為測試驅動開發 (TDD) 提供更好的支援。
非常適合由大型開發團隊支援的Web應用程式,以及需要高度控制應用程式行為的Web設計師。
ASP.NET MVC - 模式
MVC(模型-檢視-控制器)設計模式實際上已經存在了幾十年,並且已在許多不同的技術中使用。從Smalltalk到C++再到Java,現在到C#和.NET都使用這種設計模式來構建使用者介面。
以下是MVC模式的一些顯著特徵:
最初它在1979年被稱為Thing-Model-View-Editor,後來簡化為Model-View-Controller。
它是一種強大而優雅的分離應用程式內關注點的方法(例如,將資料訪問邏輯與顯示邏輯分開),並且非常適用於Web應用程式。
它明確的關注點分離確實會增加應用程式設計的一點點額外複雜性,但非凡的好處超過了額外的努力。
MVC架構模式將應用程式的使用者介面(UI)分成三個主要部分。
模型 - 一組描述您正在處理的資料以及業務邏輯的類。
檢視 - 定義應用程式的UI將如何顯示。它是一個純HTML,決定UI的外觀。
控制器 - 一組處理來自使用者、整體應用程式流程和特定於應用程式的邏輯的類。
MVC背後的理念
其理念是,您將有一個稱為檢視的元件,它唯一負責呈現此使用者介面,無論是HTML還是桌面應用程式上的UI小部件。
檢視與模型對話,該模型包含檢視需要顯示的所有資料。檢視通常幾乎沒有任何邏輯。
在Web應用程式中,檢視可能根本沒有任何程式碼與其關聯。它可能只包含HTML,然後是一些表示式,說明從模型中獲取資料片段並將其插入到您在檢視中構建的HTML模板中的正確位置。
組織一切的是控制器。當HTTP請求到達MVC應用程式時,該請求將被路由到控制器,然後由控制器與資料庫、檔案系統或模型對話。
ASP.NET MVC - 環境設定
MVC開發工具包含在Visual Studio 2012及更高版本中。它也可以安裝在Visual Studio 2010 SP1/Visual Web Developer 2010 Express SP1上。如果您使用的是Visual Studio 2010,您可以使用Web平臺安裝程式安裝MVC 4 http://www.microsoft.com
Microsoft 提供 Visual Studio 的免費版本,其中還包含 SQL Server,可以從 https://www.visualstudio.com 下載
安裝
步驟1 - 下載完成後,執行安裝程式。將顯示以下對話方塊。
步驟2 - 單擊“安裝”按鈕,它將啟動安裝過程。
安裝過程成功完成後,您將看到以下對話方塊。
步驟3 - 關閉此對話方塊,如果需要,重新啟動計算機。
步驟4 - 從“開始”選單開啟Visual Studio,將開啟以下對話方塊。僅第一次準備時需要一段時間。
完成後,您將看到如下螢幕截圖所示的Visual Studio主視窗。
您現在可以開始您的應用程式了。
ASP.NET MVC - 入門
在本章中,我們將研究ASP.NET MVC的一個簡單的可執行示例。我們將在這裡構建一個簡單的Web應用程式。要建立ASP.NET MVC應用程式,我們將使用Visual Studio 2015,其中包含建立、測試和部署MVC框架應用程式所需的所有功能。
建立ASP.Net MVC應用程式
以下是使用Visual Studio中提供的專案模板建立專案步驟:
步驟1 - 開啟Visual Studio。單擊“檔案”→“新建”→“專案”選單選項。
將開啟一個新的專案對話方塊。
步驟2 - 從左窗格中選擇“模板”→“Visual C#”→“Web”。
步驟3 - 在中間窗格中,選擇ASP.NET Web應用程式。
步驟4 - 在“名稱”欄位中輸入專案名稱MVCFirstApp,然後單擊“確定”繼續。您將看到以下對話方塊,要求您設定ASP.NET專案的初始內容。
步驟5 - 為簡單起見,選擇“空”選項,並在“新增資料夾和核心引用”部分中選中MVC複選框。單擊“確定”。
它將建立一個具有最少預定義內容的基本MVC專案。
Visual Studio建立專案後,您將在解決方案資源管理器視窗中看到許多檔案和資料夾。
正如您所知,我們是從空專案模板建立的ASP.Net MVC專案,因此目前應用程式沒有任何可執行的內容。
步驟6 - 從“除錯”→“啟動除錯”選單選項執行此應用程式,您將看到404 未找到錯誤。
預設瀏覽器是Internet Explorer,但您可以從工具欄中選擇已安裝的任何瀏覽器。
新增控制器
要刪除404未找到錯誤,我們需要新增一個控制器來處理所有傳入的請求。
步驟1 - 要新增控制器,請右鍵單擊解決方案資源管理器中的控制器資料夾,然後選擇“新增”→“控制器”。
它將顯示“新增腳手架”對話方塊。
步驟2 - 選擇MVC 5控制器 - 空選項,然後單擊“新增”按鈕。
將出現“新增控制器”對話方塊。
步驟3 - 將名稱設定為HomeController,然後單擊“新增”按鈕。
您將在Controllers資料夾中看到一個新的C#檔案HomeController.cs,它也在Visual Studio中開啟以進行編輯。
步驟4 - 為此示例,讓我們透過使用以下程式碼更改名為Index的操作方法來修改控制器類。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFirstApp.Controllers {
public class HomeController : Controller {
// GET: Home
public string Index(){
return "Hello World, this is ASP.Net MVC Tutorials";
}
}
}
步驟5 - 執行此應用程式,您將看到瀏覽器顯示Index操作方法的結果。
ASP.NET MVC - 生命週期
在本章中,我們將討論整個MVC管道以及HTTP請求在其遍歷ASP.NET中的MVC框架時的生命週期。從高層次來看,生命週期只是一個用於處理某種型別的請求或更改應用程式狀態的一系列步驟或事件。您可能已經熟悉各種框架生命週期,這個概念並非MVC獨有。
例如,ASP.NET Web窗體平臺具有複雜頁面生命週期。其他.NET平臺,如Windows Phone應用程式,也有其自身的應用程式生命週期。所有這些平臺都具有一個共同點,無論使用何種技術,理解處理管道都能幫助您更好地利用可用功能,MVC也不例外。
MVC 具有兩個生命週期:
- 應用程式生命週期
- 請求生命週期
應用程式生命週期
應用程式生命週期是指應用程式程序實際開始執行IIS到停止執行的時間段。這由應用程式啟動檔案中的應用程式啟動和結束事件標記。
請求生命週期
這是每次我們的應用程式處理HTTP請求時發生的一系列事件。
每個MVC應用程式的入口點都始於路由。ASP.NET平臺接收到請求後,它透過URL路由模組確定如何處理該請求。
模組是可以連線到應用程式生命週期並新增功能的.NET元件。路由模組負責將傳入的URL與我們在應用程式中定義的路由匹配。
所有路由都與一個關聯的路由處理程式相關聯,這是MVC框架的入口點。
MVC框架負責將路由資料轉換為可以處理請求的具體控制器。建立控制器後,下一步是**動作執行**。一個名為**動作呼叫器**的元件查詢並選擇合適的動作方法來呼叫控制器。
準備我們的動作結果後,下一個階段觸發,即**結果執行**。MVC 將宣告結果與執行結果分開。如果結果是檢視型別,則將呼叫檢視引擎,它負責查詢和呈現我們的檢視。
如果結果不是檢視,則動作結果將自行執行。此結果執行將生成對原始HTTP請求的實際響應。
ASP.NET MVC - 路由
路由是將HTTP請求定向到控制器的過程,此處理的功能在System.Web.Routing中實現。此程式集不是ASP.NET MVC的一部分。它實際上是ASP.NET執行時的一部分,並隨ASP.NET作為.NET 3.5 SP1正式釋出。
MVC框架使用**System.Web.Routing**,但ASP.NET動態資料也使用它。MVC框架利用路由將請求定向到控制器。Global.asax檔案是應用程式的一部分,您將在其中定義應用程式的路由。
這是我們之前章節中建立的MVC應用程式Global.asax中應用程式啟動事件的程式碼。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCFirstApp {
public class MvcApplication : System.Web.HttpApplication {
protected void Application_Start(){
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
}
以下是RouteConfig類的實現,其中包含一個方法RegisterRoutes。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCFirstApp {
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes){
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new{ controller = "Home", action = "Index", id = UrlParameter.Optional});
}
}
}
您將定義路由,這些路由將URL對映到特定的控制器操作。操作只是控制器上的一個方法。它還可以從該URL中提取引數並將它們作為引數傳遞到方法中。
因此,在應用程式中定義的此路由是預設路由。如上面的程式碼所示,當您看到一個表單為(something)/(something)/(something)的URL到達時,第一部分是控制器名稱,第二部分是操作名稱,第三部分是ID引數。
理解路由
MVC應用程式使用ASP.NET路由系統,該系統決定URL如何對映到控制器和操作。
當Visual Studio建立MVC專案時,它會新增一些預設路由以幫助我們開始。執行應用程式時,您會看到Visual Studio已將瀏覽器定向到埠63664。您幾乎肯定會看到瀏覽器請求的URL中不同的埠號,因為Visual Studio在建立專案時會分配一個隨機埠。
在最後一個示例中,我們添加了一個HomeController,因此您還可以請求以下任何URL,它們將被定向到HomeController上的Index操作。
https://:63664/Home/
https://:63664/Home/Index
當瀏覽器請求http://mysite/或http://mysite/Home時,它會返回HomeController的Index方法的輸出。
您也可以透過更改瀏覽器中的URL來嘗試此操作。在此示例中,它是https://:63664/,只是埠可能不同。
如果將/Home或/Home/Index附加到URL並按“Enter”按鈕,您將看到MVC應用程式的相同結果。
正如您在此案例中看到的那樣,約定是:我們有一個名為HomeController的控制器,此HomeController將成為我們MVC應用程式的起點。
Visual Studio為新專案建立的預設路由假定您將遵循此約定。但是,如果您想遵循您自己的約定,則需要修改路由。
自定義約定
您當然可以新增您自己的路由。如果您不喜歡這些操作名稱,如果您有不同的ID引數,或者您只是對站點的URL結構有所不同,那麼您可以新增您自己的路由條目。
讓我們來看一個簡單的例子。假設我們有一個包含程序列表的頁面。以下是將路由到程序頁面的程式碼。
routes.MapRoute(
"Process",
"Process/{action}/{id}",
defaults: new{
controller = "Process", action = "List ", id = UrlParameter.Optional}
);
當有人進來尋找一個帶有Process/Action/Id的URL時,他們將轉到Process Controller。我們可以使操作略有不同,預設操作,我們可以將其設為List而不是Index。
現在到達的請求看起來像localhosts/process。路由引擎將使用此路由配置將其傳遞,因此它將使用List的預設操作。
以下是完整的類實現。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCFirstApp{
public class RouteConfig{
public static void RegisterRoutes(RouteCollection routes){
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Process", "Process/{action}/{id}",
defaults: new{
controller = " Process", action = "List ", id =
UrlParameter.Optional});
routes.MapRoute(
name: "Default", url: "{controller}/{action}/{id}",
defaults: new{
controller = "Home", action = "Index", id =
UrlParameter.Optional});
}
}
}
**步驟1** - 執行此操作並使用以下URL請求程序頁面 **https://:63664/Process**
您將看到HTTP 404,因為路由引擎正在查詢ProcessController,但它不可用。
**步驟2** - 透過右鍵單擊解決方案資源管理器中的Controllers資料夾並選擇Add → Controller來建立ProcessController。
它將顯示“新增腳手架”對話方塊。
**步驟3** - 選擇MVC 5 Controller – Empty選項,然後單擊“Add”按鈕。
將出現“新增控制器”對話方塊。
**步驟4** - 將名稱設定為ProcessController,然後單擊“Add”按鈕。
現在,您將在Controllers資料夾中看到一個新的C#檔案ProcessController.cs,它也可以在Visual Studio中開啟進行編輯。
現在我們的預設操作將是List,因此我們希望在這裡使用List操作而不是Index。
**步驟5** - 將返回型別從ActionResult更改為string,並使用以下程式碼從此操作方法返回一些字串。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFirstApp.Controllers{
public class ProcessController : Controller{
// GET: Process
public string List(){
return "This is Process page";
}
}
}
**步驟6** - 當您再次執行此應用程式時,您將看到預設路由的結果。當您指定以下URL時,https://:63664/Process/List,您將看到ProcessController的結果。
ASP.NET MVC - 控制器
控制器本質上是ASP.NET MVC應用程式的中心單元。它是第一個接收者,它與傳入的HTTP請求互動。因此,控制器決定選擇哪個模型,然後它從模型中獲取資料並將其傳遞給相應的檢視,之後渲染檢視。實際上,控制器控制著應用程式的整體流程,接收輸入並呈現正確的輸出。
控制器是從System.Web.Mvc.Controller繼承的C#類,它是內建的控制器基類。控制器中的每個公共方法都被稱為操作方法,這意味著您可以透過某個URL從Web呼叫它來執行操作。
MVC約定是將控制器放在Visual Studio在設定專案時建立的Controllers資料夾中。
讓我們透過建立一個新的ASP.Net MVC專案來看一個簡單的控制器示例。
**步驟1** - 開啟Visual Studio,然後單擊“檔案”→“新建”→“專案”選單選項。
將開啟一個新的專案對話方塊。
步驟2 - 從左窗格中選擇“模板”→“Visual C#”→“Web”。
步驟3 - 在中間窗格中,選擇ASP.NET Web應用程式。
**步驟4** - 在“名稱”欄位中輸入專案名稱“MVCControllerDemo”,然後單擊“確定”繼續。您將看到以下對話方塊,提示您設定ASP.NET專案的初始內容。
**步驟5** - 為簡便起見,選擇“Empty”選項,然後選中“Add folders and core references for”部分中的MVC複選框,然後單擊“確定”。
它將建立一個具有最少預定義內容的基本MVC專案。
Visual Studio建立專案後,您將在解決方案資源管理器視窗中看到許多檔案和資料夾。
由於我們是從空專案模板建立ASP.Net MVC專案的,因此目前應用程式沒有任何內容可以執行。
**步驟6** - 透過右鍵單擊解決方案資源管理器中的Controllers資料夾來新增EmployeeController。選擇Add → Controller。
它將顯示“新增腳手架”對話方塊。
**步驟7** - 選擇MVC 5 Controller – Empty選項,然後單擊“Add”按鈕。
將出現“新增控制器”對話方塊。
**步驟8** - 將名稱設定為EmployeeController,然後單擊“Add”按鈕。
您將在Controllers資料夾中看到一個新的C#檔案EmployeeController.cs,它也可以在Visual Studio中開啟進行編輯。
現在,在這個應用程式中,我們將為Employee控制器新增一個帶有預設路由的自定義路由。
**步驟1** - 轉到“App_Start”資料夾下的“RouteConfig.cs”檔案,並新增以下路由。
routes.MapRoute(
"Employee", "Employee/{name}", new{
controller = "Employee", action = "Search", name =
UrlParameter.Optional });
以下是RouteConfig.cs檔案的完整實現。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCControllerDemo {
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes){
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Employee", "Employee/{name}", new{
controller = "Employee", action = "Search", name = UrlParameter.Optional });
routes.MapRoute(
name: "Default", url: "{controller}/{action}/{id}", defaults: new{
controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}
}
考慮這樣一種情況:任何使用者都來搜尋員工,並指定URL“Employee/Mark”。在這種情況下,Mark將被視為引數名稱,而不是操作方法。所以在這種情況下,我們的預設路由將無法正常工作。
為了在傳遞引數時從瀏覽器獲取傳入值,MVC框架提供了一種簡單的解決此問題的方法。這是透過在Action方法中使用引數來實現的。
**步驟2** - 使用以下程式碼更改EmployeeController類。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCControllerDemo.Controllers {
public class EmployeeController : Controller {
// GET: Employee
public ActionResult Search(string name){
var input = Server.HtmlEncode(name);
return Content(input);
}
}
}
如果向操作方法新增引數,則MVC框架將查詢與引數名稱匹配的值。它將應用所有可能的組合來查詢引數值。它將在路由資料、查詢字串等中搜索。
因此,如果您請求“/Employee/Mark”,則MVC框架將決定我需要一個名為“UserInput”的引數,然後將從URL中選擇Mark,並將其自動傳遞。
Server.HtmlEncode 會簡單地將任何型別的惡意指令碼轉換為純文字。當編譯並執行上述程式碼並請求以下 URL https://:61465/Employee/Mark 時,您將獲得以下輸出。
正如您在上面的螢幕截圖中看到的,Mark 是從 URL 中獲取的。
ASP.NET MVC - 操作
ASP.NET MVC Action 方法負責執行請求並生成響應。預設情況下,它以 ActionResult 的形式生成響應。操作通常與使用者互動具有一對一對映關係。
例如,在瀏覽器中輸入 URL,點選任何特定連結,提交表單等。每次使用者互動都會向伺服器傳送請求。在每種情況下,請求的 URL 都包含 MVC 框架用於呼叫操作方法的資訊。操作方法的一個限制是它們必須是例項方法,因此它們不能是靜態方法。也沒有返回值限制。因此您可以返回字串、整數等。
請求處理
操作是 MVC 應用程式中最終的請求目標,它使用控制器基類。讓我們來看看請求處理過程。
當 URL 到達時,例如 /Home/index,UrlRoutingModule 會檢查並理解路由表中配置的內容知道如何處理該 URL。
UrlRoutingModule 將我們在路由表中配置的資訊組合在一起,並將控制權交給 MVC 路由處理程式。
MVC 路由處理程式將控制器傳遞給 MvcHandler,它是一個 HTTP 處理程式。
MvcHandler 使用控制器工廠例項化控制器,它知道要例項化哪個控制器,因為它在 RouteData 中查詢該控制器值。
一旦 MvcHandler 有了一個控制器,MvcHandler 只知道 IController 介面,因此它只是告訴控制器執行。
當它告訴控制器執行時,它已從 MVC 的控制器基類派生。Execute 方法建立一個操作呼叫器並告訴該操作呼叫器去查詢要呼叫的方法,查詢要呼叫的操作。
操作呼叫器再次檢視 RouteData 並找到從路由引擎傳遞過來的 action 引數。
操作型別
操作基本上返回不同型別的操作結果。ActionResult 類是所有操作結果的基類。以下是不同型別的操作結果及其行為的列表。
| 序號 | 名稱和行為 |
|---|---|
| 1 | ContentResult 返回字串 |
| 2 | FileContentResult 返回檔案內容 |
| 3 | FilePathResult 返回檔案內容 |
| 4 | FileStreamResult 返回檔案內容 |
| 5 | EmptyResult 不返回任何內容 |
| 6 | JavaScriptResult 返回要執行的指令碼 |
| 7 | JsonResult 返回 JSON 格式的資料 |
| 8 | RedirectToResult 重定向到指定的 URL |
| 9 | HttpUnauthorizedResult 返回 403 HTTP 狀態碼 |
| 10 | RedirectToRouteResult 重定向到不同的操作/不同的控制器操作 |
| 11 | ViewResult 作為檢視引擎的響應接收 |
| 12 | PartialViewResult 作為檢視引擎的響應接收 |
讓我們來看一下上一章中我們建立的 EmployeeController 的一個簡單示例。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCControllerDemo.Controllers {
public class EmployeeController : Controller{
// GET: Employee
public ActionResult Search(string name){
var input = Server.HtmlEncode(name);
return Content(input);
}
}
}
當您請求以下 URL https://:61465/Employee/Mark 時,您將收到以下輸出作為操作。
新增控制器
讓我們新增另一個控制器。
步驟 1 - 右鍵單擊 Controllers 資料夾並選擇新增 → 控制器。
它將顯示“新增腳手架”對話方塊。
步驟2 - 選擇MVC 5控制器 - 空選項,然後單擊“新增”按鈕。
將出現“新增控制器”對話方塊。
步驟 3 - 將名稱設定為 CustomerController 並單擊“新增”按鈕。
現在您將在 Controllers 資料夾中看到一個新的 C# 檔案“CustomerController.cs”,它也可以在 Visual Studio 中開啟進行編輯。
同樣,新增另一個名為 HomeController 的控制器。以下是 HomeController.cs 類的實現。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCControllerDemo.Controllers {
public class HomeController : Controller{
// GET: Home
public string Index(){
return "This is Home Controller";
}
}
}
步驟 4 - 執行此應用程式,您將收到以下輸出。
步驟 5 - 在我們上面建立的 Customer 控制器中新增以下程式碼。
public string GetAllCustomers(){
return @"<ul>
<li>Ali Raza</li>
<li>Mark Upston</li>
<li>Allan Bommer</li>
<li>Greg Jerry</li>
</ul>";
}
步驟 6 - 執行此應用程式並請求 https://:61465/Customer/GetAllCustomers。您將看到以下輸出。
您還可以重定向到同一控制器的操作,甚至重定向到不同的控制器。
以下是一個簡單的示例,我們將透過使用以下程式碼更改 HomeController 中的程式碼來從 HomeController 重定向到 Customer Controller。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCControllerDemo.Controllers{
public class HomeController : Controller{
// GET: Home
public ActionResult Index(){
return RedirectToAction("GetAllCustomers","Customer");
}
}
}
如您所見,我們使用了 RedirectToAction() 方法 ActionResult,它接受兩個引數:操作名稱和控制器名稱。
執行此應用程式後,您將看到預設路由會將其重定向到 /Customer/GetAllCustomers
ASP.NET MVC - 過濾器
在 ASP.NET MVC 中,控制器定義的操作方法通常與可能的互動有一一對應的關係,但有時您希望在呼叫操作方法之前或執行操作方法之後執行邏輯。
為支援這一點,ASP.NET MVC 提供了過濾器。過濾器是自定義類,它們提供宣告性和程式設計方式來向控制器操作方法新增操作前和操作後行為。
操作過濾器
操作過濾器是一個屬性,您可以將其應用於控制器操作或整個控制器,以修改操作的執行方式。ASP.NET MVC 框架包含多個操作過濾器:
OutputCache - 將控制器操作的輸出快取指定時間。
HandleError - 處理執行控制器操作時引發的錯誤。
Authorize - 允許您限制對特定使用者或角色的訪問。
過濾器型別
ASP.NET MVC 框架支援四種不同型別的過濾器:
授權過濾器 - 實現 IAuthorizationFilter 屬性。
操作過濾器 - 實現 IActionFilter 屬性。
結果過濾器 - 實現 IResultFilter 屬性。
異常過濾器 - 實現 IExceptionFilter 屬性。
過濾器按上述順序執行。例如,授權過濾器總是在操作過濾器之前執行,異常過濾器總是在所有其他型別的過濾器之後執行。
授權過濾器用於為控制器操作實現身份驗證和授權。例如,Authorize 過濾器就是一個授權過濾器的示例。
讓我們透過建立一個新的 ASP.Net MVC 專案來檢視一個簡單的示例。
步驟 1 - 開啟 Visual Studio 並單擊檔案 → 新建 → 專案選單選項。
將開啟一個新的專案對話方塊。
步驟2 - 從左窗格中選擇“模板”→“Visual C#”→“Web”。
步驟3 - 在中間窗格中,選擇ASP.NET Web應用程式。
步驟 4 - 在“名稱”欄位中輸入專案名稱 MVCFiltersDemo 並單擊確定以繼續,您將看到以下對話方塊,要求您設定 ASP.NET 專案的初始內容。
**步驟5** - 為簡便起見,選擇“Empty”選項,然後選中“Add folders and core references for”部分中的MVC複選框,然後單擊“確定”。
它將建立一個具有最少預定義內容的基本MVC專案。
步驟 6 - 要新增控制器,請右鍵單擊解決方案資源管理器中的控制器資料夾,然後選擇新增 → 控制器。
它將顯示“新增腳手架”對話方塊。
**步驟7** - 選擇MVC 5 Controller – Empty選項,然後單擊“Add”按鈕。
將出現“新增控制器”對話方塊。
步驟 8 - 將名稱設定為 HomeController 並單擊“新增”按鈕。
您將在 Controllers 資料夾中看到一個新的 C# 檔案“HomeController.cs”,它也可以在 Visual Studio 中開啟進行編輯。
應用操作過濾器
操作過濾器可以應用於單個控制器操作或整個控制器。例如,操作過濾器 OutputCache 應用於名為 Index() 的操作,該操作返回字串。此過濾器導致操作返回的值被快取 15 秒。
為了使這個例子能夠工作,讓我們透過使用以下程式碼更改名為 Index 的操作方法來修改控制器類。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers {
public class HomeController : Controller{
// GET: Home
[OutputCache(Duration = 15)]
public string Index(){
return "This is ASP.Net MVC Filters Tutorial";
}
}
}
執行此應用程式後,您將看到瀏覽器顯示 Index 操作方法的結果。
讓我們新增另一個操作方法,它將顯示當前時間。
namespace MVCFiltersDemo.Controllers{
public class HomeController : Controller{
// GET: Home
[OutputCache(Duration = 15)]
public string Index(){
return "This is ASP.Net MVC Filters Tutorial";
}
[OutputCache(Duration = 20)]
public string GetCurrentTime(){
return DateTime.Now.ToString("T");
}
}
}
請求以下 URL,https://:62833/Home/GetCurrentTime,您將收到以下輸出。
如果您重新整理瀏覽器,您將看到相同的時間,因為操作被快取了 20 秒。20 秒後重新整理時,它將更新。
自定義過濾器
要建立您自己的自定義過濾器,ASP.NET MVC 框架提供了一個基類,稱為 ActionFilterAttribute。此類同時實現 IActionFilter 和 IResultFilter 介面,兩者都派生自 Filter 類。
讓我們透過在您的專案中建立一個名為 ActionFilters 的新資料夾來檢視自定義過濾器的簡單示例。新增一個類,為此右鍵單擊 ActionFilters 資料夾並選擇新增 → 類。
在名稱欄位中輸入“MyLogActionFilter”並單擊“新增”按鈕。
此類將派生自 ActionFilterAttribute(這是一個基類)並覆蓋以下方法。以下是 MyLogActionFilter 的完整實現。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCFiltersDemo.ActionFilters {
public class MyLogActionFilter : ActionFilterAttribute{
public override void OnActionExecuting(ActionExecutingContext filterContext){
Log("OnActionExecuting", filterContext.RouteData);
}
public override void OnActionExecuted(ActionExecutedContext filterContext){
Log("OnActionExecuted", filterContext.RouteData);
}
public override void OnResultExecuting(ResultExecutingContext filterContext){
Log("OnResultExecuting", filterContext.RouteData);
}
public override void OnResultExecuted(ResultExecutedContext filterContext){
Log("OnResultExecuted", filterContext.RouteData);
}
private void Log(string methodName, RouteData routeData){
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format(
"{0} controller:{1} action:{2}", methodName, controllerName, actionName);
Debug.WriteLine(message, "Action Filter Log");
}
}
}
現在讓我們使用以下程式碼將日誌過濾器應用於 HomeController。
using MVCFiltersDemo.ActionFilters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers {
[MyLogActionFilter]
public class HomeController : Controller{
// GET: Home
[OutputCache(Duration = 10)]
public string Index(){
return "This is ASP.Net MVC Filters Tutorial";
}
[OutputCache(Duration = 10)]
public string GetCurrentTime(){
return DateTime.Now.ToString("T");
}
}
}
執行應用程式,然後觀察輸出視窗。
如上面的螢幕截圖所示,操作處理的各個階段都記錄到 Visual Studio 輸出視窗中。
ASP.NET MVC - 選擇器
操作選擇器是可以應用於操作方法的屬性,用於影響響應請求時呼叫哪個操作方法。它幫助路由引擎選擇正確的操作方法來處理特定請求。
當您編寫操作方法時,它扮演著非常重要的角色。這些選擇器將根據操作方法前面給出的修改後的名稱來決定方法呼叫的行為。它通常用於為操作方法的名稱設定別名。
操作選擇器屬性有三種類型:
- ActionName
- NonAction
- ActionVerbs
ActionName
此類表示一個屬性,用於操作的名稱。它還允許開發人員使用與方法名稱不同的操作名稱。
讓我們來看一下上一章中包含兩個操作方法的 HomeController 的一個簡單示例。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers {
public class HomeController : Controller{
// GET: Home
public string Index(){
return "This is ASP.Net MVC Filters Tutorial";
}
public string GetCurrentTime(){
return DateTime.Now.ToString("T");
}
}
}
讓我們透過在 GetCurrentTime() 上方編寫 [ActionName("CurrentTime")] 來為 GetCurrentTime 應用 ActionName 選擇器,如下面的程式碼所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers {
public class HomeController : Controller{
// GET: Home
public string Index(){
return "This is ASP.Net MVC Filters Tutorial";
}
[ActionName("CurrentTime")]
public string GetCurrentTime(){
return DateTime.Now.ToString("T");
}
}
}
現在執行此應用程式並在瀏覽器中輸入以下 URL https://:62833/Home/CurrentTime,您將收到以下輸出。
您可以看到我們在上面的 URL 中使用了 CurrentTime 代替原始操作名稱 GetCurrentTime。
NonAction
NonAction 是另一個內建屬性,它指示控制器的公共方法不是操作方法。當您希望某個方法不被視為操作方法時,可以使用它。
讓我們透過在 HomeController 中新增另一個方法並應用 NonAction 屬性來檢視一個簡單的示例,如下面的程式碼所示。
using MVCFiltersDemo.ActionFilters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers {
public class HomeController : Controller{
// GET: Home
public string Index(){
return "This is ASP.Net MVC Filters Tutorial";
}
[ActionName("CurrentTime")]
public string GetCurrentTime(){
return TimeString();
}
[NonAction]
public string TimeString(){
return "Time is " + DateTime.Now.ToString("T");
}
}
}
新的方法 TimeString 從 GetCurrentTime() 呼叫,但您不能在 URL 中將其用作操作。
讓我們執行此應用程式並在瀏覽器中指定以下 URL https://:62833/Home/CurrentTime。您將收到以下輸出。
現在讓我們檢查 URL 中作為操作的 /TimeString 並看看會發生什麼。
您可以看到它給出了“404—未找到”錯誤。
ActionVerbs
您可以應用的另一個選擇器過濾器是 ActionVerbs 屬性。因此,這限制了特定操作對特定 HttpVerbs 的指示。您可以定義兩個具有相同名稱的不同操作方法,但一個操作方法響應 HTTP Get 請求,另一個操作方法響應 HTTP Post 請求。
MVC 框架支援以下 ActionVerbs。
- HttpGet
- HttpPost
- HttpPut
- HttpDelete
- HttpOptions
- HttpPatch
讓我們來看一個簡單的示例,我們將建立 EmployeeController。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCControllerDemo.Controllers {
public class EmployeeController : Controller{
// GET: Employee
public ActionResult Search(string name = “No name Entered”){
var input = Server.HtmlEncode(name);
return Content(input);
}
}
}
現在讓我們使用以下程式碼新增另一個具有相同名稱的操作方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCControllerDemo.Controllers {
public class EmployeeController : Controller{
// GET: Employee
//public ActionResult Index()
//{
// return View();
//}
public ActionResult Search(string name){
var input = Server.HtmlEncode(name);
return Content(input);
}
public ActionResult Search(){
var input = "Another Search action";
return Content(input);
}
}
}
執行此應用程式時,會報錯,因為MVC框架無法確定為請求選擇哪個操作方法。
讓我們使用以下程式碼,為想要作為響應的操作指定HttpGet ActionVerb。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCControllerDemo.Controllers {
public class EmployeeController : Controller{
// GET: Employee
//public ActionResult Index()
//{
// return View();
//}
public ActionResult Search(string name){
var input = Server.HtmlEncode(name);
return Content(input);
}
[HttpGet]
public ActionResult Search(){
var input = "Another Search action";
return Content(input);
}
}
}
執行此應用程式後,您將收到以下輸出。
ASP.NET MVC - 檢視
在ASP.NET MVC應用程式中,沒有像頁面這樣的東西,並且在URL中指定路徑時,它也不包含任何直接對應於頁面的內容。在ASP.NET MVC應用程式中最接近頁面的東西被稱為檢視。
在ASP.NET MVC應用程式中,所有傳入的瀏覽器請求都由控制器處理,這些請求被對映到控制器操作。控制器操作可能會返回一個檢視,也可能會執行其他型別的操作,例如重定向到另一個控制器操作。
讓我們透過建立一個新的ASP.NET MVC專案來看一個簡單的檢視示例。
步驟 1 - 開啟 Visual Studio 並單擊檔案 → 新建 → 專案選單選項。
將開啟一個新的專案對話方塊。
步驟2 - 從左窗格中選擇“模板”→“Visual C#”→“Web”。
步驟3 - 在中間窗格中,選擇ASP.NET Web應用程式。
步驟4 - 在“名稱”欄位中輸入專案名稱“MVCViewDemo”,然後單擊“確定”繼續。您將看到以下對話方塊,要求您為ASP.NET專案設定初始內容。
**步驟5** - 為簡便起見,選擇“Empty”選項,然後選中“Add folders and core references for”部分中的MVC複選框,然後單擊“確定”。
它將建立一個具有最少預定義內容的基本MVC專案。現在我們需要新增控制器。
步驟6 - 右鍵單擊解決方案資源管理器中的控制器資料夾,然後選擇“新增”→“控制器”。
它將顯示“新增腳手架”對話方塊。
**步驟7** - 選擇MVC 5 Controller – Empty選項,然後單擊“Add”按鈕。
將出現“新增控制器”對話方塊。
步驟 8 - 將名稱設定為 HomeController 並單擊“新增”按鈕。
您將在Controllers資料夾中看到一個新的C#檔案“HomeController.cs”,它也可以在Visual Studio中開啟進行編輯。
讓我們更新HomeController.cs檔案,其中包含兩個操作方法,如下面的程式碼所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCViewDemo.Controllers {
public class HomeController : Controller{
// GET: Home
public ActionResult Index(){
return View();
}
public string Mycontroller(){
return "Hi, I am a controller";
}
}
}
步驟9 - 執行此應用程式,並在瀏覽器中的URL後面附加/Home/MyController,然後按Enter鍵。您將收到以下輸出。
由於MyController操作只是返回字串,因此要從操作返回檢視,我們需要先新增檢視。
步驟10 - 在新增檢視之前,讓我們新增另一個操作,它將返回預設檢視。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCViewDemo.Controllers {
public class HomeController : Controller{
// GET: Home
public ActionResult Index(){
return View();
}
public string Mycontroller(){
return "Hi, I am a controller";
}
public ActionResult MyView(){
return View();
}
}
}
步驟11 - 執行此應用程式,並在瀏覽器中的URL後面附加/Home/MyView,然後按Enter鍵。您將收到以下輸出。
您可以在這裡看到一個錯誤,這個錯誤實際上非常具有描述性,它告訴我們找不到MyView檢視。
步驟12 - 要新增檢視,請右鍵單擊MyView操作內部,然後選擇“新增檢視”。
它將顯示“新增檢視”對話方塊,並將新增預設名稱。
步驟13 - 取消選中“使用佈局頁”複選框,然後單擊“新增”按鈕。
我們現在在檢視中有了預設程式碼。
步驟14 - 使用以下程式碼在此檢視中新增一些文字。
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>MyView</title>
</head>
<body>
<div>
Hi, I am a view
</div>
</body>
</html>
步驟15 - 執行此應用程式,並在瀏覽器中的URL後面附加/Home/MyView。按Enter鍵,您將收到以下輸出。
您現在可以看到檢視中的文字。
ASP.NET MVC - 資料模型
在本章中,我們將討論在ASP.NET MVC框架應用程式中構建模型。一個模型儲存根據控制器的命令檢索到的資料,並在檢視中顯示。
模型是類的集合,您將在其中處理資料和業務邏輯。因此,基本上模型是特定於業務領域的容器。它用於與資料庫互動。它還可以用於操作資料以實現業務邏輯。
讓我們透過建立一個新的ASP.Net MVC專案來看一個簡單的模型示例。
步驟1 - 開啟Visual Studio。單擊“檔案”→“新建”→“專案”選單選項。
將開啟一個新的專案對話方塊。
步驟2 - 從左窗格中選擇“模板”→“Visual C#”→“Web”。
步驟3 - 在中間窗格中,選擇ASP.NET Web應用程式。
步驟4 - 在“名稱”欄位中輸入專案名稱“MVCSimpleApp”,然後單擊“確定”繼續。您將看到以下對話方塊,要求您為ASP.NET專案設定初始內容。
**步驟5** - 為簡便起見,選擇“Empty”選項,然後選中“Add folders and core references for”部分中的MVC複選框,然後單擊“確定”。
它將建立一個具有最少預定義內容的基本MVC專案。
現在我們需要新增一個控制器。
步驟6 - 右鍵單擊解決方案資源管理器中的控制器資料夾,然後選擇“新增”→“控制器”。
它將顯示“新增腳手架”對話方塊。
步驟7 - 選擇MVC 5控制器 - 帶有讀/寫操作的選項。此模板將建立一個帶有控制器預設操作的Index方法。這也將列出其他方法,如Edit/Delete/Create。
步驟8 - 單擊“新增”按鈕,將出現“新增控制器”對話方塊。
步驟9 - 將名稱設定為EmployeeController,然後單擊“新增”按鈕。
步驟10 - 您將在Controllers資料夾中看到一個新的C#檔案“EmployeeController.cs”,它在Visual Studio中開啟,並帶有一些預設操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCSimpleApp.Controllers {
public class EmployeeController : Controller{
// GET: Employee
public ActionResult Index(){
return View();
}
// GET: Employee/Details/5
public ActionResult Details(int id){
return View();
}
// GET: Employee/Create
public ActionResult Create(){
return View();
}
// POST: Employee/Create
[HttpPost]
public ActionResult Create(FormCollection collection){
try{
// TODO: Add insert logic here
return RedirectToAction("Index");
}catch{
return View();
}
}
// GET: Employee/Edit/5
public ActionResult Edit(int id){
return View();
}
// POST: Employee/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection){
try{
// TODO: Add update logic here
return RedirectToAction("Index");
}catch{
return View();
}
}
// GET: Employee/Delete/5
public ActionResult Delete(int id){
return View();
}
// POST: Employee/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection){
try{
// TODO: Add delete logic here
return RedirectToAction("Index");
}catch{
return View();
}
}
}
}
讓我們新增一個模型。
步驟11 - 右鍵單擊解決方案資源管理器中的Models資料夾,然後選擇“新增”→“類”。
您將看到“新增新項”對話方塊。
步驟12 - 在中間面板中選擇“類”,並在名稱欄位中輸入Employee.cs。
步驟13 - 使用以下程式碼向Employee類新增一些屬性。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MVCSimpleApp.Models {
public class Employee{
public int ID { get; set; }
public string Name { get; set; }
public DateTime JoiningDate { get; set; }
public int Age { get; set; }
}
}
讓我們透過新增另一個方法來更新EmployeeController.cs檔案,該方法將返回員工列表。
[NonAction]
public List<Employee> GetEmployeeList(){
return new List<Employee>{
new Employee{
ID = 1,
Name = "Allan",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 23
},
new Employee{
ID = 2,
Name = "Carson",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 45
},
new Employee{
ID = 3,
Name = "Carson",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 37
},
new Employee{
ID = 4,
Name = "Laura",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 26
},
};
}
步驟14 - 按以下程式碼所示更新index操作方法。
public ActionResult Index(){
var employees = from e in GetEmployeeList()
orderby e.ID
select e;
return View(employees);
}
步驟15 - 執行此應用程式,並在瀏覽器中的URL後面附加/employee,然後按Enter鍵。您將看到以下輸出。
如上面的螢幕截圖所示,出現了一個錯誤,這個錯誤實際上非常具有描述性,它告訴我們找不到Index檢視。
步驟16 - 因此,要新增檢視,請右鍵單擊Index操作內部,然後選擇“新增檢視”。
它將顯示“新增檢視”對話方塊,並將新增預設名稱。
步驟17 - 從“模板”下拉列表中選擇“列表”,從“模型類”下拉列表中選擇“Employee”,並取消選中“使用佈局頁”複選框,然後單擊“新增”按鈕。
它將在此檢視中為您新增一些預設程式碼。
@model IEnumerable<MVCSimpleApp.Models.Employee>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>Index</title>
</head>
<body>
<p>@Html.ActionLink("Create New", "Create")</p>
<table class = "table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.JoiningDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.JoiningDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Age)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
@Html.ActionLink("Details", "Details", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}
</table>
</body>
</html>
步驟18 - 執行此應用程式,您將收到以下輸出。
將顯示員工列表。
ASP.NET MVC - 輔助方法
在ASP.Net Web窗體中,開發人員使用工具箱在任何特定頁面上新增控制元件。但是,在ASP.NET MVC應用程式中,沒有可用於將HTML控制元件拖放到檢視上的工具箱。在ASP.NET MVC應用程式中,如果您要建立檢視,它應該包含HTML程式碼。因此,那些剛接觸MVC,尤其是具有Web窗體背景的開發人員會覺得這有點困難。
為了克服這個問題,ASP.NET MVC提供了HtmlHelper類,其中包含不同的方法,可以幫助您以程式設計方式建立HTML控制元件。所有HtmlHelper方法都生成HTML並將結果作為字串返回。最終的HTML是由這些函式在執行時生成的。HtmlHelper類旨在生成UI,不應在控制器或模型中使用。
有不同型別的輔助方法。
Createinputs - 為文字框和按鈕建立輸入。
Createlinks - 建立基於路由表資訊的連結。
Createforms - 建立可以釋出回我們的操作或釋出回不同控制器上的操作的表單標籤。
| 序號 | 方法和描述 |
|---|---|
| 1 | Action(String) 過載。呼叫指定子操作方法並將結果作為HTML字串返回。(由ChildActionExtensions定義) |
| 2 | Action(String, Object) 過載。使用指定引數呼叫指定子操作方法並將結果作為HTML字串返回。(由ChildActionExtensions定義) |
| 3 | Action(String, RouteValueDictionary) 過載。使用指定的引數呼叫指定子操作方法並將結果作為HTML字串返回。(由ChildActionExtensions定義) |
| 4 | Action(String, String) 過載。使用指定的控制器名稱呼叫指定子操作方法並將結果作為HTML字串返回。(由ChildActionExtensions定義) |
| 5 | Action(String, String, Object) 過載。使用指定的引數和控制器名稱呼叫指定子操作方法並將結果作為HTML字串返回。(由ChildActionExtensions定義) |
| 6 | Action(String, String, RouteValueDictionary) 過載。使用指定的引數和控制器名稱呼叫指定子操作方法並將結果作為HTML字串返回。(由ChildActionExtensions定義) |
| 7 | ActionLink(String, String) 過載。(由LinkExtensions定義) |
| 8 | ActionLink(String, String, Object) 過載。(由LinkExtensions定義) |
| 9 | ActionLink(String, String, Object, Object) 過載。(由LinkExtensions定義) |
| 10 | ActionLink(String, String, RouteValueDictionary) 過載。(由LinkExtensions定義) |
| 11 | ActionLink(String, String, RouteValueDictionary, IDictionary<String, Object>) 過載。(由LinkExtensions定義) |
| 12 | ActionLink(String, String, String) 過載。(由LinkExtensions定義) |
| 13 | ActionLink(String, String, String, Object, Object) 過載。(由LinkExtensions定義) |
| 14 | ActionLink(String, String, String, RouteValueDictionary, IDictionary<String, Object>) 過載。(由LinkExtensions定義) |
| 15 | ActionLink(String, String, String, String, String, String, Object, Object) 過載。(由LinkExtensions定義) |
| 16 | ActionLink(String, String, String, String, String, String, RouteValueDictionary, IDictionary<String, Object>) 過載。(由LinkExtensions定義) |
| 17 | BeginForm() 過載。將開啟的<form>標籤寫入響應。該表單使用POST方法,請求由檢視的操作方法處理。(由FormExtensions定義) |
| 18 | BeginForm(Object) 過載。將開啟的<form>標籤寫入響應,並在action屬性中包含路由值。該表單使用POST方法,請求由檢視的操作方法處理。(由FormExtensions定義) |
| 19 | BeginForm(RouteValueDictionary) 過載。將開啟的<form>標籤寫入響應,並在action屬性中包含來自路由值字典的路由值。該表單使用POST方法,請求由檢視的操作方法處理。(由FormExtensions定義。) |
| 20 | BeginForm(String, String) 過載。將開啟的<form>標籤寫入響應,並將action標籤設定為指定的控制器和操作。該表單使用POST方法。(由FormExtensions定義) |
| 21 | BeginForm(String, String, FormMethod) 過載。將開啟的<form>標籤寫入響應,並將action標籤設定為指定的控制器和操作。該表單使用指定的HTTP方法。(由FormExtensions定義) |
| 22 | BeginForm(String, String, FormMethod, IDictionary<String, Object>) 過載。將開啟的<form>標籤寫入響應,並將action標籤設定為指定的控制器和操作。該表單使用指定的HTTP方法,幷包含來自字典的HTML屬性。(由FormExtensions定義) |
| 23 | BeginForm(String, String, FormMethod, Object) 過載。將開啟的<form>標籤寫入響應,並將action標籤設定為指定的控制器和操作。該表單使用指定的HTTP方法,幷包含HTML屬性。(由FormExtensions定義) |
| 24 | BeginForm(String, String, Object) 過載。向響應中寫入一個起始<form>標記,並將 action 標記設定為指定的控制器、操作和路由值。表單使用 POST 方法。(由 FormExtensions 定義) |
| 25 | BeginForm(String, String, Object, FormMethod) 過載。向響應中寫入一個起始<form>標記,並將 action 標記設定為指定的控制器、操作和路由值。表單使用指定的 HTTP 方法。(由 FormExtensions 定義) |
| 26 | BeginForm(String, String, Object, FormMethod, Object) 過載。向響應中寫入一個起始<form>標記,並將 action 標記設定為指定的控制器、操作和路由值。表單使用指定的 HTTP 方法幷包含 HTML 屬性。(由 FormExtensions 定義) |
| 27 | BeginForm(String, String, RouteValueDictionary) 過載。向響應中寫入一個起始<form>標記,並將 action 標記設定為來自路由值字典中指定的控制器、操作和路由值。表單使用 POST 方法。(由 FormExtensions 定義) |
| 28 | BeginForm(String, String, RouteValueDictionary, FormMethod) 過載。向響應中寫入一個起始<form>標記,並將 action 標記設定為來自路由值字典中指定的控制器、操作和路由值。表單使用指定的 HTTP 方法。(由 FormExtensions 定義) |
| 29 | BeginForm(String, String, RouteValueDictionary, FormMethod, IDictionary<String, Object>) 過載。向響應中寫入一個起始<form>標記,並將 action 標記設定為來自路由值字典中指定的控制器、操作和路由值。表單使用指定的 HTTP 方法,幷包含來自字典的 HTML 屬性。(由 FormExtensions 定義) |
| 30 | BeginRouteForm(Object) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 31 | BeginRouteForm(RouteValueDictionary) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 32 | BeginRouteForm(String) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 33 | BeginRouteForm(String, FormMethod) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 34 | BeginRouteForm(String, FormMethod, IDictionary<String, Object>) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 35 | BeginRouteForm(String, FormMethod, Object) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 36 | BeginRouteForm(String, Object) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 37 | BeginRouteForm(String, Object, FormMethod) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 38 | BeginRouteForm(String, Object, FormMethod, Object) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 39 | BeginRouteForm(String, RouteValueDictionary) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 40 | BeginRouteForm(String, RouteValueDictionary, FormMethod) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 41 | BeginRouteForm(String, RouteValueDictionary, FormMethod, IDictionary<String, Object>) 過載。向響應中寫入一個起始<form>標記。當用戶提交表單時,請求將由路由目標處理。(由 FormExtensions 定義) |
| 42 | CheckBox(String) 過載。使用指定的 HTML 輔助方法和表單欄位的名稱返回一個複選框輸入元素。(由 InputExtensions 定義) |
| 43 | CheckBox(String, Boolean) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和一個值來指示覆選框是否被選中,返回一個複選框輸入元素。(由 InputExtensions 定義) |
| 44 | CheckBox(String, Boolean, IDictionary<String, Object>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、一個值來指示覆選框是否被選中以及 HTML 屬性,返回一個複選框輸入元素。(由 InputExtensions 定義) |
| 45 | CheckBox(String, Boolean, Object) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、一個值來指示覆選框是否被選中以及 HTML 屬性,返回一個複選框輸入元素。(由 InputExtensions 定義) |
| 46 | CheckBox(String, IDictionary<String, Object>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和 HTML 屬性,返回一個複選框輸入元素。(由 InputExtensions 定義) |
| 47 | CheckBox(String, Object) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和 HTML 屬性,返回一個複選框輸入元素。(由 InputExtensions 定義) |
| 48 | Display(String) 過載。返回由字串表示式表示的物件中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 49 | Display(String, Object) 過載。使用附加檢視資料返回由字串表示式表示的物件中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 50 | Display(String, String) 過載。使用指定的模板返回由表示式表示的物件中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 51 | Display(String, String, Object) 過載。使用指定的模板和附加檢視資料返回由表示式表示的物件中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 52 | Display(String, String, String) 過載。使用指定的模板和 HTML 欄位 ID 返回由表示式表示的物件中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 53 | Display(String, String, String, Object) 過載。使用指定的模板、HTML 欄位 ID 和附加檢視資料返回由表示式表示的物件中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 54 | DisplayForModel() 過載。返回模型中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 55 | DisplayForModel(Object) 過載。使用附加檢視資料返回模型中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 56 | DisplayForModel(String) 過載。使用指定的模板返回模型中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 57 | DisplayForModel(String, Object) 過載。使用指定的模板和附加檢視資料返回模型中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 58 | DisplayForModel(String, String) 過載。使用指定的模板和 HTML 欄位 ID 返回模型中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 59 | DisplayForModel(String, String, Object) 過載。使用指定的模板、HTML 欄位 ID 和附加檢視資料返回模型中每個屬性的 HTML 標記。(由 DisplayExtensions 定義) |
| 60 | DisplayName(String) 獲取顯示名稱。(由 DisplayNameExtensions 定義) |
| 61 | DisplayNameForModel() 獲取模型的顯示名稱。(由 DisplayNameExtensions 定義) |
| 62 | DisplayText(String) 返回由指定表示式表示的物件中每個屬性的 HTML 標記。(由 DisplayTextExtensions 定義) |
| 63 | DropDownList(String) 過載。使用指定的 HTML 輔助方法和表單欄位的名稱返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 64 | DropDownList(String, IEnumerable<SelectListItem>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和指定的列表項返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 65 | DropDownList(String, IEnumerable<SelectListItem>, IDictionary<String, Object>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、指定的列表項和指定的 HTML 屬性返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 66 | DropDownList(String, IEnumerable<SelectListItem>, Object) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、指定的列表項和指定的 HTML 屬性返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 67 | DropDownList(String, IEnumerable<SelectListItem>, String) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、指定的列表項和一個選項標籤返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 68 | DropDownList(String, IEnumerable<SelectListItem>, String, IDictionary<String, Object>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、指定的列表項、一個選項標籤和指定的 HTML 屬性返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 69 | DropDownList(String, IEnumerable<SelectListItem>, String, Object) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、指定的列表項、一個選項標籤和指定的 HTML 屬性返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 70 | DropDownList(String, String) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和一個選項標籤返回一個單選選擇元素。(由 SelectExtensions 定義) |
| 71 | Editor(String) 過載。為由表示式表示的物件中每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 72 | Editor(String, Object) 過載。使用附加檢視資料為由表示式表示的物件中每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 73 | Editor(String, String) 過載。使用指定的模板為由表示式表示的物件中每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 74 | Editor(String, String, Object) 過載。使用指定的模板和附加檢視資料為由表示式表示的物件中每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 75 | Editor(String, String, String) 過載。使用指定的模板和 HTML 欄位名稱為由表示式表示的物件中每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 76 | Editor(String, String, String, Object) 過載。使用指定的模板、HTML 欄位名稱和附加檢視資料為由表示式表示的物件中每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 77 | EditorForModel() 過載。為模型中的每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 78 | EditorForModel(Object) 過載。使用附加檢視資料為模型中的每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 79 | EditorForModel(String) 過載。使用指定的模板為模型中的每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 80 | EditorForModel(String, Object) 過載。使用指定的模板和附加檢視資料為模型中的每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 81 | EditorForModel(String, String) 過載。使用指定的模板名稱和 HTML 欄位名稱為模型中的每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 82 | EditorForModel(String, String, Object) 過載。使用模板名稱、HTML 欄位名稱和附加檢視資料為模型中的每個屬性返回一個 HTML 輸入元素。(由 EditorExtensions 定義) |
| 83 | EndForm() 向響應中呈現結束</form>標記。(由 FormExtensions 定義) |
| 84 | Hidden(String) 過載。使用指定的 HTML 輔助方法和表單欄位的名稱返回一個隱藏的輸入元素。(由 InputExtensions 定義) |
| 85 | Hidden(String, Object) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和值返回一個隱藏的輸入元素。(由 InputExtensions 定義) |
| 86 | Hidden(String, Object, IDictionary<String, Object>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、值和 HTML 屬性返回一個隱藏的輸入元素。(由 InputExtensions 定義) |
| 87 | Hidden(String, Object, Object) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、值和 HTML 屬性返回一個隱藏的輸入元素。(由 InputExtensions 定義) |
| 88 | Id(String) 獲取 HtmlHelper 字串的 ID。(由 NameExtensions 定義) |
| 89 | IdForModel() 獲取 HtmlHelper 字串的 ID。(由 NameExtensions 定義) |
| 90 | Label(String) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 91 | Label(String, IDictionary<String, Object>) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 92 | Label(String, Object) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 93 | Label(String, String) 過載。使用標籤文字返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 94 | Label(String, String, IDictionary<String, Object>) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 95 | Label(String, String, Object) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 96 | LabelForModel() 過載。返回一個 HTML 標籤元素和由模型表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 97 | LabelForModel(IDictionary<String, Object>) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 98 | LabelForModel(Object) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 99 | LabelForModel(String) 過載。使用標籤文字返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 100 | LabelForModel(String, IDictionary<String, Object>) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 101 | LabelForModel(String, Object) 過載。返回一個 HTML 標籤元素和由指定表示式表示的屬性的屬性名稱。(由 LabelExtensions 定義) |
| 102 | ListBox(String) 過載。使用指定的 HTML 輔助方法和表單欄位的名稱返回一個多選選擇元素。(由 SelectExtensions 定義) |
| 103 | ListBox(String, IEnumerable<SelectListItem>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和指定的列表項返回一個多選選擇元素。(由 SelectExtensions 定義) |
| 104 | ListBox(String, IEnumerable<SelectListItem>, IDictionary<String, Object>) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱、指定的列表項和指定的 HTML 屬性返回一個多選選擇元素。(由 SelectExtensions 定義) |
| 105 | ListBox(String, IEnumerable<SelectListItem>, Object) 過載。使用指定的 HTML 輔助方法、表單欄位的名稱和指定的列表項返回一個多選選擇元素。(由 SelectExtensions 定義) |
| 106 | Name(String) 獲取由表示式表示的物件的完整 HTML 欄位名稱。(由 NameExtensions 定義) |
| 107 | NameForModel() 獲取由表示式表示的物件的完整 HTML 欄位名稱。(由 NameExtensions 定義。) |
| 108 | Partial(String) 過載。將指定的區域性檢視呈現為 HTML 編碼的字串。(由 PartialExtensions 定義) |
| 109 | Partial(String, Object) 過載。將指定的區域性檢視呈現為 HTML 編碼的字串。(由 PartialExtensions 定義) |
| 110 | Partial(String, Object, ViewDataDictionary) 過載。將指定的區域性檢視呈現為 HTML 編碼的字串。(由 PartialExtensions 定義) |
| 111 | Partial(String, ViewDataDictionary) 過載。將指定的區域性檢視呈現為 HTML 編碼的字串。(由 PartialExtensions 定義) |
| 112 | Password(String) 過載。使用指定的HTML輔助方法和表單欄位名稱返回密碼輸入元素。(由InputExtensions定義) |
| 113 | Password(String, Object) 過載。使用指定的HTML輔助方法、表單欄位名稱和值返回密碼輸入元素。(由InputExtensions定義) |
| 114 | Password(String, Object, IDictionary<String, Object>) 過載。使用指定的HTML輔助方法、表單欄位名稱、值和HTML屬性返回密碼輸入元素。(由InputExtensions定義) |
| 115 | Password(String, Object, Object) 過載。使用指定的HTML輔助方法、表單欄位名稱、值和HTML屬性返回密碼輸入元素。(由InputExtensions定義) |
| 116 | RadioButton(String, Object) 過載。返回一個單選按鈕輸入元素,用於呈現互斥選項。(由InputExtensions定義) |
| 117 | RadioButton(String, Object, Boolean) 過載。返回一個單選按鈕輸入元素,用於呈現互斥選項。(由InputExtensions定義) |
| 118 | RadioButton(String, Object, Boolean, IDictionary<String, Object>) 過載。返回一個單選按鈕輸入元素,用於呈現互斥選項。(由InputExtensions定義) |
| 119 | RadioButton(String, Object, Boolean, Object) 過載。返回一個單選按鈕輸入元素,用於呈現互斥選項。(由InputExtensions定義) |
| 120 | RadioButton(String, Object, IDictionary<String, Object>) 過載。返回一個單選按鈕輸入元素,用於呈現互斥選項。(由InputExtensions定義) |
| 121 | RadioButton(String, Object, Object) 過載。返回一個單選按鈕輸入元素,用於呈現互斥選項。(由InputExtensions定義) |
| 122 | RenderAction(String) 過載。呼叫指定的子操作方法,並將結果內聯渲染到父檢視中。(由ChildActionExtensions定義) |
| 123 | RenderAction(String, Object) 過載。使用指定引數呼叫指定的子操作方法,並將結果內聯渲染到父檢視中。(由ChildActionExtensions定義) |
| 124 | RenderAction(String, RouteValueDictionary) 過載。使用指定引數呼叫指定的子操作方法,並將結果內聯渲染到父檢視中。(由ChildActionExtensions定義) |
| 125 | RenderAction(String, String) 過載。使用指定的控制器名稱呼叫指定的子操作方法,並將結果內聯渲染到父檢視中。(由ChildActionExtensions定義) |
| 126 | RenderAction(String, String, Object) 過載。使用指定的引數和控制器名稱呼叫指定的子操作方法,並將結果內聯渲染到父檢視中。(由ChildActionExtensions定義) |
| 127 | RenderAction(String, String, RouteValueDictionary) 過載。使用指定的引數和控制器名稱呼叫指定的子操作方法,並將結果內聯渲染到父檢視中。(由ChildActionExtensions定義) |
| 128 | RenderPartial(String) 過載。使用指定的HTML輔助方法呈現指定的區域性檢視。(由RenderPartialExtensions定義) |
| 129 | RenderPartial(String, Object) 過載。呈現指定的區域性檢視,並傳遞當前ViewDataDictionary物件的副本,但Model屬性設定為指定模型。(由RenderPartialExtensions定義) |
| 130 | RenderPartial(String, Object, ViewDataDictionary) 過載。呈現指定的區域性檢視,用指定的ViewDataDictionary物件替換區域性檢視的ViewData屬性,並將檢視資料的Model屬性設定為指定的模型。(由RenderPartialExtensions定義) |
| 131 | RenderPartial(String, ViewDataDictionary) 過載。呈現指定的區域性檢視,用指定的ViewDataDictionary物件替換其ViewData屬性。(由RenderPartialExtensions定義) |
| 132 | RouteLink(String, Object) 過載。(由LinkExtensions定義) |
| 133 | RouteLink(String, Object, Object) 過載。(由LinkExtensions定義) |
| 134 | RouteLink(String, RouteValueDictionary) 過載。(由LinkExtensions定義) |
| 135 | RouteLink(String, RouteValueDictionary, IDictionary<String, Object>) 過載。(由LinkExtensions定義) |
| 136 | RouteLink(String, String) 過載。(由LinkExtensions定義) |
| 137 | RouteLink(String, String, Object) 過載。(由LinkExtensions定義) |
| 138 | RouteLink(String, String, Object, Object) 過載。(由LinkExtensions定義) |
| 139 | RouteLink(String, String, RouteValueDictionary) 過載。(由LinkExtensions定義) |
| 140 | RouteLink(String, String, RouteValueDictionary, IDictionary<String, Object>) 過載。(由LinkExtensions定義) |
| 141 | RouteLink(String, String, String, String, String, Object, Object) 過載。(由LinkExtensions定義) |
| 142 | RouteLink(String, String, String, String, String, RouteValueDictionary, IDictionary<String, Object>) 過載。(由LinkExtensions定義) |
| 143 | TextArea(String) 過載。使用指定的HTML輔助方法和表單欄位名稱返回指定的文字區域元素。(由TextAreaExtensions定義。) |
| 144 | TextArea(String, IDictionary<String, Object>) 過載。使用指定的HTML輔助方法、表單欄位名稱和指定的HTML屬性返回指定的文字區域元素。(由TextAreaExtensions定義) |
| 145 | TextArea(String, Object) 過載。使用指定的HTML輔助方法和HTML屬性返回指定的文字區域元素。(由TextAreaExtensions定義) |
| 146 | TextArea(String, String) 過載。使用指定的HTML輔助方法、表單欄位名稱和文字內容返回指定的文字區域元素。(由TextAreaExtensions定義) |
| 147 | TextArea(String, String, IDictionary<String, Object>) 過載。使用指定的HTML輔助方法、表單欄位名稱、文字內容和指定的HTML屬性返回指定的文字區域元素。(由TextAreaExtensions定義) |
| 148 | TextArea(String, String, Int32, Int32, IDictionary<String, Object>) 過載。使用指定的HTML輔助方法、表單欄位名稱、文字內容、行數和列數以及指定的HTML屬性返回指定的文字區域元素。(由TextAreaExtensions定義) |
| 149 | TextArea(String, String, Int32, Int32, Object) 過載。使用指定的HTML輔助方法、表單欄位名稱、文字內容、行數和列數以及指定的HTML屬性返回指定的文字區域元素。(由TextAreaExtensions定義) |
| 150 | TextArea(String, String, Object) 過載。使用指定的HTML輔助方法、表單欄位名稱、文字內容和指定的HTML屬性返回指定的文字區域元素。(由TextAreaExtensions定義) |
| 151 | TextBox(String) 過載。使用指定的HTML輔助方法和表單欄位名稱返回文字輸入元素。(由InputExtensions定義) |
| 152 | TextBox(String, Object) 過載。使用指定的HTML輔助方法、表單欄位名稱和值返回文字輸入元素。(由InputExtensions定義) |
| 153 | TextBox(String, Object, IDictionary<String, Object>) 過載。使用指定的HTML輔助方法、表單欄位名稱、值和HTML屬性返回文字輸入元素。(由InputExtensions定義) |
| 154 | TextBox(String, Object, Object) 過載。使用指定的HTML輔助方法、表單欄位名稱、值和HTML屬性返回文字輸入元素。(由InputExtensions定義) |
| 155 | TextBox(String, Object, String) 過載。返回一個文字輸入元素。(由InputExtensions定義) |
| 156 | TextBox(String, Object, String, IDictionary<String, Object>) 過載。返回一個文字輸入元素。(由InputExtensions定義) |
| 157 | TextBox(String, Object, String, Object) 過載。返回一個文字輸入元素。(由InputExtensions定義) |
| 158 | Validate(String) 檢索指定模型的驗證元資料,並將每個規則應用於資料欄位。(由ValidationExtensions定義) |
| 159 | ValidationMessage(String) 過載。如果ModelStateDictionary物件中指定欄位存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 160 | ValidationMessage(String, IDictionary<String, Object>) 過載。如果ModelStateDictionary物件中指定欄位存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義。) |
| 161 | ValidationMessage(String, IDictionary<String, Object>, String) 過載。如果ModelStateDictionary物件中指定條目存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 162 | ValidationMessage(String, Object) 過載。如果ModelStateDictionary物件中指定欄位存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 163 | ValidationMessage(String, Object, String) 過載。如果ModelStateDictionary物件中指定條目存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 164 | ValidationMessage(String, String) 過載。如果ModelStateDictionary物件中指定欄位存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 165 | ValidationMessage(String, String, IDictionary<String, Object>) 過載。如果ModelStateDictionary物件中指定欄位存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 166 | ValidationMessage(String, String, IDictionary<String, Object>, String) 過載。如果ModelStateDictionary物件中指定條目存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 167 | ValidationMessage(String, String, Object) 過載。如果ModelStateDictionary物件中指定欄位存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 168 | ValidationMessage(String, String, Object, String) 過載。如果ModelStateDictionary物件中指定條目存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 169 | ValidationMessage(String, String, String) 過載。如果ModelStateDictionary物件中指定條目存在錯誤,則顯示驗證訊息。(由ValidationExtensions定義) |
| 170 | ValidationSummary() 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素)。(由ValidationExtensions定義) |
| 171 | ValidationSummary(Boolean) 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素),並可以選擇僅顯示模型級錯誤。(由ValidationExtensions定義) |
| 172 | ValidationSummary(Boolean, String) 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素),並可以選擇僅顯示模型級錯誤。(由ValidationExtensions定義) |
| 173 | ValidationSummary(Boolean, String, IDictionary<String, Object>) 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素),並可以選擇僅顯示模型級錯誤。(由ValidationExtensions定義) |
| 174 | ValidationSummary(Boolean, String, IDictionary<String, Object>, String) 過載。(由ValidationExtensions定義) |
| 175 | ValidationSummary(Boolean, String, Object) 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素),並可以選擇僅顯示模型級錯誤。(由ValidationExtensions定義) |
| 176 | ValidationSummary(Boolean, String, Object, String) 過載。(由ValidationExtensions定義) |
| 177 | ValidationSummary(Boolean, String, String) 過載。(由ValidationExtensions定義) |
| 178 | ValidationSummary(String) 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素)。(由ValidationExtensions定義) |
| 179 | ValidationSummary(String, IDictionary<String, Object>) 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素)。(由ValidationExtensions定義) |
| 180 | ValidationSummary(String, IDictionary<String, Object>, String) 過載。(由ValidationExtensions定義) |
| 181 | ValidationSummary(String, Object) 過載。返回ModelStateDictionary物件中驗證訊息的無序列表(ul元素)。(由ValidationExtensions定義) |
| 182 | ValidationSummary(String, Object, String) 過載。(由ValidationExtensions定義) |
| 183 | ValidationSummary(String, String) 過載。(由ValidationExtensions定義) |
| 184 | Value(String) 過載。提供一種機制來建立與ASP.NET MVC模型繫結器和模板相容的自定義HTML標記。(由ValueExtensions定義) |
| 185 | Value(String, String) 過載。提供一種機制來建立與ASP.NET MVC模型繫結器和模板相容的自定義HTML標記。(由ValueExtensions定義) |
| 186 | ValueForModel() 過載。提供一種機制來建立與ASP.NET MVC模型繫結器和模板相容的自定義HTML標記。(由ValueExtensions定義) |
| 187 | ValueForModel(String) 過載。提供一種機制來建立與ASP.NET MVC模型繫結器和模板相容的自定義HTML標記。(由ValueExtensions定義) |
如果您檢視上一章中從EmployeeController索引操作生成的檢視,您將看到許多以Html開頭的操作,例如Html.ActionLink和Html.DisplayNameFor等,如下面的程式碼所示。
@model IEnumerable<MVCSimpleApp.Models.Employee>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>Index</title>
</head>
<body>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class = "table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.JoiningDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.JoiningDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Age)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
@Html.ActionLink("Details", "Details", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}
</table>
</body>
</html>
此HTML是繼承自ViewPage基類的屬性。因此,它在所有檢視中都可用,並且它返回一個稱為HTML Helper型別的例項。
讓我們來看一個簡單的例子,在這個例子中,我們將允許使用者編輯員工。因此,此編輯操作將使用大量不同的HTML Helper。
如果您檢視上面的程式碼,您將在最後看到以下HTML Helper方法
@Html.ActionLink("Edit", "Edit", new { id = item.ID })
在ActionLink helper中,第一個引數是連結“Edit”,第二個引數是控制器中的操作方法,也是“Edit”,第三個引數ID是您要編輯的任何特定員工的ID。
讓我們透過新增靜態列表來更改EmployeeController類,並使用以下程式碼更改索引操作。
public static List<Employee> empList = new List<Employee>{
new Employee{
ID = 1,
Name = "Allan",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 23
},
new Employee{
ID = 2,
Name = "Carson",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 45
},
new Employee{
ID = 3,
Name = "Carson",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 37
},
new Employee{
ID = 4,
Name = "Laura",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 26
},
};
public ActionResult Index(){
var employees = from e in empList
orderby e.ID
select e;
return View(employees);
}
讓我們更新Edit操作。您將看到兩個Edit操作,一個用於GET,一個用於POST。讓我們更新用於Get的Edit操作,它在引數中只有Id,如下面的程式碼所示。
// GET: Employee/Edit/5
public ActionResult Edit(int id){
List<Employee> empList = GetEmployeeList();
var employee = empList.Single(m => m.ID == id);
return View(employee);
}
現在,我們知道我們有Edit操作,但我們沒有這些操作的任何檢視。因此,我們也需要新增一個檢視。為此,右鍵單擊Edit操作並選擇新增檢視。
您將看到檢視的預設名稱。從模板下拉列表中選擇Edit,從模型類下拉列表中選擇Employee。
以下是Edit檢視中的預設實現。
@model MVCSimpleApp.Models.Employee
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>Edit</title>
</head>
<body>
@using (Html.BeginForm()){
@Html.AntiForgeryToken()
<div class = "form-horizontal">
<h4>Employee</h4>
<hr />
@Html.ValidationSummary(
true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.ID)
<div class = "form-group">
@Html.LabelFor(
model => model.Name, htmlAttributes: new{
@class = "control-label col-md-2" })
<div class = "col-md-10">
@Html.EditorFor(model => model.Name, new{
htmlAttributes = new {
@class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new{
@class = "text-danger" })
</div>
</div>
<div class = "form-group">
@Html.LabelFor(
model => model.JoiningDate, htmlAttributes: new{
@class = "control-label col-md-2" })
<div class = "col-md-10">
@Html.EditorFor(
model => model.JoiningDate, new{
htmlAttributes = new{ @class = "form-control" } })
@Html.ValidationMessageFor(
model => model.JoiningDate, "", new{
@class = "text-danger" })
</div>
</div>
<div class = "form-group">
@Html.LabelFor(
model => model.Age, htmlAttributes: new{
@class = "control-label col-md-2" })
<div class = "col-md-10">
@Html.EditorFor(
model => model.Age, new{
htmlAttributes = new{ @class = "form-control" } })
@Html.ValidationMessageFor(
model => model.Age, "", new{
@class = "text-danger" })
</div>
</div>
<div class = "form-group">
<div class = "col-md-offset-2 col-md-10">
<input type = "submit" value = "Save" class = "btn btn-default"/>
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
</body>
</html>
正如您所看到的,使用了許多helper方法。“HTML.BeginForm”編寫一個起始表單標籤。它還確保當用戶單擊“儲存”按鈕時,方法將為“Post”。
Html.BeginForm非常有用,因為它允許您更改URL、更改方法等。
在上面的程式碼中,您將看到另一個HTML helper,即“@HTML.HiddenFor”,它發出隱藏欄位。
MVC框架足夠智慧,可以知道此ID欄位在模型類中已提及,因此需要防止對其進行編輯,這就是為什麼它被標記為隱藏的原因。
Html.LabelFor HTML Helper在螢幕上建立標籤。如果在進行更改時輸入錯誤,Html.ValidationMessageFor helper將顯示正確的錯誤訊息。
我們還需要更改POST的Edit操作,因為一旦更新員工,它就會呼叫此操作。
// POST: Employee/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection){
try{
var employee = empList.Single(m => m.ID == id);
if (TryUpdateModel(employee)){
//To Do:- database code
return RedirectToAction("Index");
}
return View(employee);
}catch{
return View();
}
}
讓我們執行此應用程式並請求以下URL https://:63004/employee。您將收到以下輸出。
單擊任何特定員工的編輯連結,例如單擊Allan的編輯連結。您將看到以下檢視。
讓我們將年齡從23更改為29,然後單擊“儲存”按鈕,然後您將在索引檢視上看到更新後的年齡。
ASP.NET MVC - 模型繫結
ASP.NET MVC模型繫結允許您將HTTP請求資料與模型對映。它是使用瀏覽器在HTTP請求中傳送的資料建立.NET物件的過程。對於ASP.Net MVC的新手ASP.NET Web Forms開發人員來說,當它到達控制器的操作方法時,檢視中的值如何轉換為模型類,大多數人對此感到困惑,因此這種轉換是由模型繫結器完成的。
模型繫結是HTTP請求和C#操作方法之間精心設計的橋樑。它使開發人員能夠輕鬆處理表單(檢視)上的資料,因為POST和GET會自動轉換為您指定的DataModel。ASP.NET MVC使用預設繫結器在後臺完成此操作。
讓我們來看一個簡單的例子,在這個例子中,我們在上一章的專案中新增一個“建立檢視”,我們將看到如何將這些值從檢視獲取到EmployeeController操作方法。
以下是POST的建立操作方法。
// POST: Employee/Create
[HttpPost]
public ActionResult Create(FormCollection collection){
try{
// TODO: Add insert logic here
return RedirectToAction("Index");
}catch{
return View();
}
}
右鍵單擊建立操作方法,然後選擇新增檢視…
它將顯示“新增檢視”對話方塊。
正如您在上面的螢幕截圖中看到的,預設名稱已提及。現在從模板下拉列表中選擇建立,從模型類下拉列表中選擇Employee。
您將在Create.cshtml檢視中看到預設程式碼。
@model MVCSimpleApp.Models.Employee
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>Create</title>
</head>
<body>
@using (Html.BeginForm()){
@Html.AntiForgeryToken()
<div class = "form-horizontal">
<h4>Employee</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class = "form-group">
@Html.LabelFor(model => model.Name, htmlAttributes:
new{ @class = "control-label col-md-2" })
<div class = "col-md-10">
@Html.EditorFor(model => model.Name, new{ htmlAttributes =
new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "",
new{ @class = "text-danger" })
</div>
</div>
<div class = "form-group">
@Html.LabelFor(model => model.JoiningDate, htmlAttributes:
new{ @class = "control-label col-md-2" })
<div class = "col-md-10">
@Html.EditorFor(model => model.JoiningDate, new{ htmlAttributes =
new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.JoiningDate, "",
new { @class = "text-danger" })
</div>
</div>
<div class = "form-group">
@Html.LabelFor(model => model.Age, htmlAttributes:
new { @class = "control-label col-md-2" })
<div class = "col-md-10">
@Html.EditorFor(model => model.Age, new { htmlAttributes =
new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Age, "", new{ @class = "text-danger" })
</div>
</div>
<div class = "form-group">
<div class = "col-md-offset-2 col-md-10">
<input type = "submit" value = "Create" class = "btn btn-default"/>
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
</body>
</html>
當用戶在“建立檢視”中輸入值時,它也存在於FormCollection和Request.Form中。我們可以使用這些值中的任何一個來填充檢視中的員工資訊。
讓我們使用以下程式碼使用FormCollection建立員工。
// POST: Employee/Create
[HttpPost]
public ActionResult Create(FormCollection collection){
try {
Employee emp = new Employee();
emp.Name = collection["Name"];
DateTime jDate;
DateTime.TryParse(collection["DOB"], out jDate);
emp.JoiningDate = jDate;
string age = collection["Age"];
emp.Age = Int32.Parse(age);
empList.Add(emp);
return RedirectToAction("Index");
}catch {
return View();
}
}
執行此應用程式並請求此URL https://:63004/Employee/。您將收到以下輸出。
點選頁面頂部的“新建”連結,將跳轉到以下檢視。
讓我們輸入要新增的另一個員工的資料。
點選建立按鈕,您將看到新員工已新增到您的列表中。
在上面的示例中,我們獲取HTML檢視中所有提交的值,然後將這些值對映到Employee屬性並逐個賦值。
在這種情況下,我們還將在提交的值與模型屬性的格式不同的地方進行型別轉換。
這也被稱為手動繫結,這種實現方式對於簡單的小資料模型來說可能還不錯。但是,如果您有龐大的資料模型並且需要大量的型別轉換,那麼我們可以利用ASP.NET MVC模型繫結的強大功能和易用性。
讓我們看看我們為模型繫結做的同一個例子。
我們需要更改Create方法的引數,使其接受Employee模型物件而不是FormCollection,如下面的程式碼所示。
// POST: Employee/Create
[HttpPost]
public ActionResult Create(Employee emp){
try{
empList.Add(emp);
return RedirectToAction("Index");
}catch{
return View();
}
}
現在,模型繫結的魔力取決於提供值的HTML變數的id。
對於我們的Employee模型,HTML輸入欄位的id應該與Employee模型的屬性名稱相同,您可以看到Visual Studio在建立檢視時使用的是相同的模型屬性名稱。
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
對映預設情況下將基於屬性名稱。在這裡,我們會發現HTML輔助方法非常有用,因為這些輔助方法將生成HTML,這些HTML將具有模型繫結正常工作的正確名稱。
執行此應用程式並請求URL https://:63004/Employee/。您將看到以下輸出。
點選頁面頂部的“新建”連結,將跳轉到以下檢視。
讓我們輸入要新增的另一個員工的資料。
現在點選建立按鈕,您將看到新員工已使用ASP.Net MVC模型繫結新增到您的列表中。
ASP.NET MVC - 資料庫
在本教程中建立的所有ASP.NET MVC應用程式中,我們都將硬編碼資料從控制器傳遞到檢視模板。但是,為了構建一個真實的Web應用程式,您可能需要使用一個真實的資料庫。在本章中,我們將瞭解如何使用資料庫引擎來儲存和檢索應用程式所需的資料。
為了儲存和檢索資料,我們將使用一種名為實體框架的.NET Framework資料訪問技術來定義和使用模型。
實體框架 (EF) 支援程式碼優先技術,允許您透過編寫簡單的類來建立模型物件,然後資料庫將根據您的類動態建立,這使得開發工作流程非常簡潔和快速。
讓我們看一個簡單的例子,在這個例子中,我們將向我們的例子中新增對實體框架的支援。
步驟1 - 要安裝實體框架,請右鍵單擊您的專案,然後選擇NuGet包管理器→管理解決方案的NuGet包…
它將開啟NuGet包管理器。在搜尋框中搜索實體框架。
選擇實體框架並點選“安裝”按鈕。它將開啟預覽對話方塊。
點選確定繼續。
點選“我接受”按鈕開始安裝。
安裝實體框架後,您將在輸出視窗中看到上面的螢幕截圖中所示的訊息。
新增DBContext
我們需要向Employee模型新增另一個類,該類將與實體框架通訊,以使用以下程式碼檢索和儲存資料。
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace MVCSimpleApp.Models{
public class Employee{
public int ID { get; set; }
public string Name { get; set; }
public DateTime JoiningDate { get; set; }
public int Age { get; set; }
}
public class EmpDBContext : DbContext{
public EmpDBContext()
{ }
public DbSet<Employee> Employees { get; set; }
}
}
如上所示,EmpDBContext 派生自一個名為DbContext 的EF類。在這個類中,我們有一個名為DbSet的屬性,它基本上代表您要查詢和儲存的實體。
連線字串
我們需要在Web.config檔案的<configuration>標籤下為我們的資料庫指定連線字串。
<connectionStrings> <add name = "EmpDBContext" connectionString = "Data Source = (LocalDb)\v14.0;AttachDbFilename = |DataDirectory|\EmpDB.mdf;Initial Catalog = EmployeeDB;Integrated Security = SSPI;" providerName = "System.Data.SqlClient"/> </connectionStrings>
您實際上不需要新增EmpDBContext連線字串。如果您沒有指定連線字串,實體框架將在使用者的目錄中建立一個localDB資料庫,其名稱為DbContext類的完全限定名。為了簡化演示,我們不會新增連線字串。
現在我們需要更新EmployeeController.cs檔案,以便我們可以從資料庫中儲存和檢索資料,而不是使用硬編碼資料。
首先,我們新增一個私有的EmpDBContext類物件,然後更新Index、Create和Edit操作方法,如下面的程式碼所示。
using MVCSimpleApp.Models;
using System.Linq;
using System.Web.Mvc;
namespace MVCSimpleApp.Controllers {
public class EmployeeController : Controller{
private EmpDBContext db = new EmpDBContext();
// GET: Employee
public ActionResult Index(){
var employees = from e in db.Employees
orderby e.ID
select e;
return View(employees);
}
// GET: Employee/Create
public ActionResult Create(){
return View();
}
// POST: Employee/Create
[HttpPost]
public ActionResult Create(Employee emp){
try{
db.Employees.Add(emp);
db.SaveChanges();
return RedirectToAction("Index");
}catch{
return View();
}
}
// GET: Employee/Edit/5
public ActionResult Edit(int id){
var employee = db.Employees.Single(m => m.ID == id);
return View(employee);
}
// POST: Employee/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection){
try{
var employee = db.Employees.Single(m => m.ID == id);
if (TryUpdateModel(employee)){
//To Do:- database code
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}catch{
return View();
}
}
}
}
然後,我們使用以下URLhttps://:63004/Employee執行此應用程式。您將看到以下輸出。
您可以看到檢視上沒有資料,這是因為我們還沒有在Visual Studio建立的資料庫中新增任何記錄。
讓我們轉到SQL Server物件資源管理器,您將看到資料庫的名稱與我們在DBContext類中使用的名稱相同。
讓我們展開此資料庫,您將看到它有一個表,其中包含Employee模型類中的所有欄位。
要檢視此表中的資料,請右鍵單擊Employees表並選擇檢視資料。
您將看到目前我們沒有任何記錄。
讓我們直接在資料庫中新增一些記錄,如下面的螢幕截圖所示。
重新整理瀏覽器,您將看到資料現在已從資料庫更新到檢視。
讓我們透過單擊“新建”連結從瀏覽器新增一條記錄。它將顯示建立檢視。
讓我們在以下欄位中新增一些資料。
點選建立按鈕,它將更新索引檢視並將此新記錄新增到資料庫。
現在讓我們轉到SQL Server物件資源管理器並重新整理資料庫。右鍵單擊Employees表並選擇檢視資料選單選項。您將看到該記錄已新增到資料庫中。
ASP.NET MVC - 驗證
驗證是ASP.NET MVC應用程式中的一個重要方面。它用於檢查使用者輸入是否有效。ASP.NET MVC提供了一套易於使用的驗證方法,同時也是檢查錯誤並在必要時向用戶顯示訊息的強大方法。
DRY
DRY代表不要重複自己,是ASP.NET MVC的核心設計原則之一。從開發的角度來看,建議只在一個地方指定功能或行為,然後在整個應用程式中從該地方使用它。
這減少了您需要編寫的程式碼量,並使您編寫的程式碼更不容易出錯,也更容易維護。
向模型新增驗證
讓我們看一個在我們上一章專案中驗證的簡單示例。在這個示例中,我們將資料註釋新增到我們的模型類中,該類提供了一些內建的驗證屬性集,可以直接應用於應用程式中的任何模型類或屬性,例如Required、StringLength、RegularExpression和Range驗證屬性。
它還包含像DataType這樣的格式化屬性,這些屬性有助於格式化並且不提供任何驗證。驗證屬性指定要對應用它們的模型屬性強制執行的行為。
Required和MinimumLength屬性指示屬性必須具有值;但沒有任何東西可以阻止使用者輸入空格來滿足此驗證。RegularExpression屬性用於限制可以輸入的字元。
讓我們透過新增不同的註釋屬性來更新Employee類,如下面的程式碼所示。
using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
namespace MVCSimpleApp.Models {
public class Employee{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
public string Name { get; set; }
[Display(Name = "Joining Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime JoiningDate { get; set; }
[Range(22, 60)]
public int Age { get; set; }
}
}
現在我們還需要設定資料庫的限制。但是,SQL Server物件資源管理器中的資料庫顯示name屬性設定為NVARCHAR(MAX),如下面的螢幕截圖所示。
為了在資料庫上設定此限制,我們將使用遷移來更新模式。
從工具→NuGet包管理器→包管理器控制檯開啟包管理器控制檯視窗。
在包管理器控制檯視窗中逐一輸入以下命令。
Enable-Migrations add-migration DataAnnotations update-database
以下是執行這些命令後在包管理器控制檯視窗中的日誌。
Visual Studio還將開啟派生自DbMIgration類的類,您可以在其中看到在Up方法中更新模式約束的程式碼。
namespace MVCSimpleApp.Migrations {
using System;
using System.Data.Entity.Migrations;
public partial class DataAnnotations : DbMigration{
public override void Up(){
AlterColumn("dbo.Employees", "Name", c => c.String(maxLength: 60));
}
public override void Down(){
AlterColumn("dbo.Employees", "Name", c => c.String());
}
}
}
Name欄位的最大長度為60,這是資料庫中的新長度限制,如下面的快照所示。
執行此應用程式,並透過指定以下URLhttps://:63004/Employees/Create轉到建立檢視。
讓我們在這些欄位中輸入一些無效資料,然後單擊建立按鈕,如下面的螢幕截圖所示。
您將看到jQuery客戶端驗證檢測到錯誤,並且它還會顯示錯誤訊息。
ASP.NET MVC - 安全性
在本章中,我們將討論如何在應用程式中實現安全功能。我們還將瞭解ASP.NET包含的新的成員資格功能,以及可從ASP.NET MVC中使用的功能。在最新版本的ASP.NET中,我們可以使用以下方法管理使用者身份:-
- 雲
- SQL資料庫
- 本地Windows活動目錄
在本章中,我們還將瞭解ASP.NET的一部分的新身份元件,並瞭解如何為我們的使用者和角色自定義成員資格。
身份驗證
使用者的身份驗證意味著驗證使用者的身份。這非常重要。出於顯而易見的原因,您可能需要僅向已認證的使用者展示您的應用程式。
讓我們建立一個新的ASP.Net MVC應用程式。
點選確定繼續。
當您啟動一個新的ASP.NET應用程式時,該過程中的一個步驟是為應用程式需求配置身份驗證服務。
選擇MVC模板,您將看到“更改身份驗證”按鈕現在已啟用。
這是透過“新建專案”對話方塊中出現的“更改身份驗證”按鈕完成的。預設身份驗證是“單個使用者帳戶”。
身份驗證選項
單擊“更改”按鈕時,您將看到一個對話方塊,其中包含四個選項,如下所示。
無身份驗證
第一個選項是“無身份驗證”,當您想要構建一個不關心訪問者是誰的網站時,可以使用此選項。
它對任何人都開放,每個人都連線到每一個頁面。您以後可以隨時更改它,但“無身份驗證”選項意味著不會有任何功能來識別訪問網站的使用者。
單個使用者帳戶
第二個選項是“單個使用者帳戶”,這是傳統的基於表單的身份驗證,使用者可以訪問網站。他們可以註冊,建立登入,預設情況下,他們的使用者名稱使用一些新的ASP.NET身份功能儲存在SQL Server資料庫中,我們稍後將介紹。
密碼也儲存在資料庫中,但在儲存之前先進行雜湊處理。由於密碼已進行雜湊處理,因此您無需擔心資料庫中存在純文字密碼。
此選項通常用於您想要建立使用者身份的網際網路站點。除了允許使用者使用密碼建立本地登入名外,您還可以啟用來自Microsoft、Google、Facebook和Twitter等第三方登入名。
這允許使用者使用他們的Live帳戶或Twitter帳戶登入您的站點,他們可以選擇一個本地使用者名稱,但您無需儲存任何密碼。
本模組我們將重點講解這個選項:單個使用者帳戶選項。
工作和學校帳戶
第三個選項是使用組織帳戶,這通常用於企業應用程式,其中您將使用活動目錄聯合服務。
您可以設定 Office 365 或使用 Azure Active Directory 服務,並擁有用於內部應用程式和雲應用程式的單點登入功能。
您還需要提供應用程式 ID,因此如果基於 Azure,則您的應用程式需要在 Windows Azure 管理門戶中註冊,並且應用程式 ID 將在所有可能註冊的應用程式中唯一標識此應用程式。
Windows 身份驗證
第四個選項是 Windows 身份驗證,它非常適用於內聯網應用程式。
使用者登入到 Windows 桌面,並可以使用瀏覽器啟動位於同一防火牆內的應用程式。ASP.NET 可以自動獲取使用者的身份,即活動目錄已建立的身份。此選項不允許任何匿名訪問站點,但這又是一個可以更改的配置設定。
讓我們來看看基於表單的身份驗證,也就是所謂的單個使用者帳戶。此應用程式將使用者名稱和密碼(舊密碼)儲存在本地 SQL Server 資料庫中,建立此專案時,Visual Studio 還將新增 NuGet 包。
現在執行此應用程式,當您第一次訪問此應用程式時,您將是匿名使用者。
您還沒有可以登入的帳戶,因此您需要在此站點上註冊。
單擊“註冊”連結,您將看到以下檢視。
輸入您的電子郵件 ID 和密碼。
單擊“註冊”。現在,應用程式將識別您。
它將能夠顯示您的姓名。在下面的螢幕截圖中,您可以看到顯示了“您好,muhammad.waqas@outlook.com!”。您可以單擊它,這是一個連結到可以更改密碼的頁面。
您也可以登出、關閉、重啟,一週後再回來,您應該能夠使用之前使用的憑據登入。現在單擊“登出”按鈕,它將顯示以下頁面。
再次單擊“登入”連結,您將轉到以下頁面。
您可以使用相同的憑據再次登入。
幕後做了很多工作才能達到這一點。但是,我們要做的是檢查每個功能,看看這個 UI 是如何構建的。是什麼管理登出和登入過程?此資訊儲存在資料庫中的哪個位置?
讓我們從幾個簡單的基礎開始。首先,我們將看到如何顯示此使用者名稱。在解決方案資源管理器中開啟 View/Shared 資料夾中的 _Layout.cshtml。
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8" />
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class = "navbar navbar-inverse navbar-fixed-top">
<div class = "container">
<div class = "navbar-header">
<button type = "button" class = "navbar-toggle" datatoggle = "collapse"
data-target = ".navbar-collapse">
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new
{ area = "" }, new { @class = "navbar-brand" })
</div>
<div class = "navbar-collapse collapse">
<ul class = "nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class = "container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
有一個公共導航欄、應用程式名稱、選單,還有一個名為 _loginpartial 的正在呈現的部分檢視。這實際上是顯示使用者名稱或註冊和登入名稱的檢視。因此 _loginpartial.cshtml 也在共享資料夾中。
@using Microsoft.AspNet.Identity
@if (Request.IsAuthenticated) {
using (Html.BeginForm("LogOff", "Account", FormMethod.Post,
new { id = "logoutForm", @class = "navbar-right" })){
@Html.AntiForgeryToken()
<ul class = "nav navbar-nav navbar-right">
<li>
@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!",
"Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
</li>
<li>
<a href = "javascript:document.getElementById('logoutForm').submit()">Logoff</a>
</li>
</ul>
}
}else{
<ul class = "nav navbar-nav navbar-right">
<li>@Html.ActionLink("Register", "Register", "Account", routeValues:
null, htmlAttributes: new { id = "registerLink" })</li>
<li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null,
htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
如上所示,存在 if/else 語句。如果我們不知道使用者是誰,因為請求未經身份驗證,則此檢視將顯示註冊和登入連結。使用者可以單擊連結登入或註冊。所有這一切都是由帳戶控制器完成的。
目前,我們想知道如何獲取使用者名稱,它位於 Request.IsAuthenticated 內部。您可以看到對 User.Identity.GetUserName 的呼叫。這將檢索使用者名稱,在本例中為“muhammad.waqas@outlook.com”
授權
假設我們有一些資訊需要保護,防止未經身份驗證的使用者訪問。因此,讓我們建立一個新的控制器來顯示這些資訊,但僅當用戶登入時才顯示。
右鍵單擊控制器資料夾,然後選擇“新增”→“控制器”。
選擇 MVC 5 控制器 - 空控制器,然後單擊“新增”。
輸入名稱 SecretController 並單擊“新增”按鈕。
它內部將有兩個操作,如下面的程式碼所示。
using System.Web.Mvc;
namespace MVCSecurityDemo.Controllers{
public class SecretController : Controller{
// GET: Secret
public ContentResult Secret(){
return Content("Secret informations here");
}
public ContentResult PublicInfo(){
return Content("Public informations here");
}
}
}
執行此應用程式時,您可以訪問此資訊,無需任何身份驗證,如下面的螢幕截圖所示。
因此,只有經過身份驗證的使用者才能訪問 Secret 操作方法,而 PublicInfo 可以被任何人無身份驗證地使用。
為了保護此特定操作並阻止未經身份驗證的使用者到達此處,您可以使用 Authorize 屬性。沒有其他引數的 Authorize 屬性將確保已知使用者的身份,並且他們不是匿名使用者。
// GET: Secret
[Authorize]
public ContentResult Secret(){
return Content("Secret informations here");
}
現在再次執行此應用程式並指定相同的 URL **https://:54232/Secret/Secret**。MVC 應用程式將檢測到您無權訪問應用程式的該特定區域,它會自動將您重定向到登入頁面,在該頁面上,它將為您提供登入並嘗試返回您被拒絕訪問的應用程式區域的機會。
您可以看到它在返回 URL 中指定,這實際上告訴此頁面,如果使用者成功登入,則將其重定向回 /secret/secret。
輸入您的憑據並單擊“登入”按鈕。您將看到它直接轉到該頁面。
如果您返回主頁並登出,則無法訪問 secret 頁面。系統將再次要求您登入,但如果您轉到 /Secret/PublicInfo,即使您未經身份驗證,您也可以看到該頁面。
因此,當您不想在控制器內的每個操作上都放置授權時,在控制器中幾乎所有內容都需要授權。在這種情況下,您可以始終將此過濾器應用於控制器本身,現在此控制器內的每個操作都需要使用者進行身份驗證。
using System.Web.Mvc;
namespace MVCSecurityDemo.Controllers{
[Authorize]
public class SecretController : Controller{
// GET: Secret
public ContentResult Secret(){
return Content("Secret informations here");
}
public ContentResult PublicInfo(){
return Content("Public informations here");
}
}
}
但是,如果您確實希望任何操作保持開放,您可以使用另一個屬性覆蓋此授權規則,即 AllowAnonymous。
using System.Web.Mvc;
namespace MVCSecurityDemo.Controllers{
[Authorize]
public class SecretController : Controller{
// GET: Secret
public ContentResult Secret(){
return Content("Secret informations here");
}
[AllowAnonymous]
public ContentResult PublicInfo(){
return Content("Public informations here");
}
}
}
執行此應用程式,您可以訪問 /Secret/PublicInfo 而無需登入,但其他操作需要身份驗證。
它只允許匿名使用者進入此一項操作。
使用 Authorize 屬性,您還可以指定一些引數,例如允許某些特定使用者進入此操作。
using System.Web.Mvc;
namespace MVCSecurityDemo.Controllers{
[Authorize(Users = "ali.khan@outlook.com")]
public class SecretController : Controller{
// GET: Secret
public ContentResult Secret(){
return Content("Secret informations here");
}
[AllowAnonymous]
public ContentResult PublicInfo(){
return Content("Public informations here");
}
}
}
執行此應用程式並轉到 /secret/secret 時,它將要求您登入,因為它不是此控制器的正確使用者。
ASP.NET MVC - 快取
在本節中,我們將重點關注 ASP.NET 中最常見的技術之一,例如快取,以提高應用程式的效能。快取意味著將經常使用的內容儲存在記憶體中,以提供更好的效能。我們將瞭解如何透過利用輸出快取來顯著提高 ASP.NET MVC 應用程式的效能。
在 ASP.NET MVC 中,有一個 OutputCache 篩選器屬性可以應用,這與 Web 窗體中的輸出快取概念相同。輸出快取使您可以快取控制器操作返回的內容。
輸出快取基本上允許您將特定控制器的輸出儲存在記憶體中。因此,將來對該控制器中相同操作的任何請求都將從快取結果返回。這樣,每次呼叫相同的控制器操作時,就不需要重新生成相同的內容。
為什麼需要快取?
在許多不同的場景中,我們需要快取來提高應用程式的效能。例如,您有一個 ASP.NET MVC 應用程式,它顯示員工列表。現在,每次使用者呼叫控制器操作時,這些記錄都透過執行資料庫查詢從資料庫中檢索,它返回 Index 檢視。
因此,您可以利用輸出快取來避免每次使用者呼叫相同的控制器操作時都執行資料庫查詢。在這種情況下,檢視將從快取中檢索,而不是從控制器操作重新生成。
快取使您可以避免在伺服器上執行冗餘工作。
讓我們來看一個專案中快取的簡單示例。
[OutputCache(Duration = 60)]
public ActionResult Index(){
var employees = from e in db.Employees
orderby e.ID
select e;
return View(employees);
}
如您所見,我們在 EmployeeController 的 index 操作中添加了“OutputCache”屬性。現在,為了理解這個概念,讓我們在除錯模式下執行此應用程式,並在 Index 操作方法中插入一個斷點。
指定以下 URL **https://:63004/employee**,然後按“Enter”。您將看到斷點已命中 Index 操作方法。
按“F5”按鈕繼續,您將在檢視中看到從資料庫檢索到的員工列表。
在 60 秒內再次重新整理瀏覽器,您會發現這次斷點沒有命中。這是因為我們使用了持續時間為 60 秒的輸出快取。因此,它將在 60 秒內快取此結果,當您重新整理瀏覽器時,它將從快取中獲取結果,並且不會從資料庫伺服器載入內容。
除了 duration 引數外,還可以使用輸出快取的其他設定選項。這些設定不僅適用於 MVC 框架,而且繼承自 ASP.Net 快取。
更改輸出快取
在某些情況下,您可能需要不同的快取版本,例如,當您建立詳細資訊頁面時,然後當您單擊詳細資訊連結時,您將獲得所選員工的詳細資訊。
但首先我們需要建立詳細資訊檢視。為此,右鍵單擊 EmployeeController 的 Details 操作方法,然後選擇“新增檢視…”。
您會看到預設情況下選擇了 Details 名稱。現在從“模板”下拉列表中選擇 Details,從“模型類”下拉列表中選擇 Employee。
單擊“新增”繼續,您將看到 Details.cshtml。
@model MVCSimpleApp.Models.Employee
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>Details</title>
</head>
<body>
<div>
<h4>Employee</h4>
<hr />
<dl class = "dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.JoiningDate)
</dt>
<dd>
@Html.DisplayFor(model => model.JoiningDate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Age)
</dt>
<dd>
@Html.DisplayFor(model => model.Age)
</dd>
</dl>
</div>
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
@Html.ActionLink("Back to List", "Index")
</p>
</body>
</html>
您可以利用 [OutputCache] 屬性的 VaryByParam 屬性。當表單引數或查詢字串引數變化時,此屬性使您可以建立相同內容的不同快取版本。以下是 Details 操作的實現。
// GET: Employee/Details/5
[OutputCache(Duration = int.MaxValue, VaryByParam = "id")]
public ActionResult Details(int id){
var employee = db.Employees.SingleOrDefault(e => e.ID == id);
return View(employee);
}
編譯並執行上述程式碼後,透過指定 URL **https://:63004/employee**,您將收到以下輸出。
單擊任何連結的“詳細資訊”連結,您將看到該特定員工的詳細資訊檢視。
Details() 操作包含一個值為“Id”的 VaryByParam 屬性。當不同的 Id 引數值傳遞給控制器操作時,將生成 Details 檢視的不同快取版本。
重要的是要理解,使用 VaryByParam 屬性會導致更多快取。將為 Id 引數的每個不同版本建立 Details 檢視的不同快取版本。
快取配置檔案
您可以在 web.config 檔案中建立快取配置檔案。這是一種透過修改 [OutputCache] 屬性的屬性來配置輸出快取屬性的替代方法。它提供了一些重要的優勢,如下所示。
控制控制器操作在一箇中心位置快取內容的方式。
建立一個快取配置檔案,並將該配置檔案應用於多個控制器或控制器操作。
修改 web 配置檔案而無需重新編譯應用程式。
停用已部署到生產環境的應用程式的快取。
讓我們來看一個快取配置檔案的簡單示例,方法是在 web.config 檔案中建立快取配置檔案。
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name = "Cache10Min" duration = "600" varyByParam = "none"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
您可以使用 [OutputCache] 屬性將 Cache10Min 配置檔案應用於控制器操作,如下所示。
[OutputCache(CacheProfile = "Cache10Min")]
public ActionResult Index(){
var employees = from e in db.Employees
orderby e.ID
select e;
return View(employees);
}
執行此應用程式並指定以下 URL **https://:63004/employee**
如果您如上所示呼叫 Index() 操作,則將在 10 分鐘內返回相同的時間。
ASP.NET MVC - Razor
在本節中,我們將研究 ASP.NET MVC 應用程式中的 Razor 檢視引擎以及 Razor 存在的一些原因。Razor 是一種標記語法,允許您使用 C# 和 VB.Net 將基於伺服器的程式碼嵌入到網頁中。它不是程式語言。它是一種伺服器端標記語言。
Razor 與 ASP.NET MVC 無關,因為 Razor 是一個通用的模板引擎。你可以在任何地方使用它來生成輸出,例如 HTML。只是 ASP.NET MVC 實現了一個檢視引擎,允許我們在 MVC 應用程式中使用 Razor 來生成 HTML。
你將擁有一個模板檔案,它混合了一些文字和一些程式碼塊。你將該模板與一些資料或特定模型組合起來,模板指定資料應該出現在哪裡,然後你執行模板以生成輸出。
Razor 與 ASPX
Razor 與 ASPX 檔案的工作方式非常相似。ASPX 檔案是模板,包含文字和一些 C# 程式碼,用於指定資料應該出現在哪裡。我們執行這些檔案來生成應用程式的 HTML。
ASPX 檔案依賴於 ASP.NET 執行時才能解析和執行這些 ASPX 檔案。Razor 沒有這種依賴性。
與 ASPX 檔案不同,Razor 有一些不同的設計目標。
目標
Microsoft 希望 Razor 易於使用和學習,並在 Visual Studio 等工具中工作,以便可以使用 IntelliSense 和偵錯程式,但他們希望 Razor 與特定技術(如 ASP.NET 或 ASP.NET MVC)無關。
如果你熟悉 ASPX 檔案的生命週期,那麼你可能知道它依賴於 ASP.NET 執行時才能解析和執行這些 ASPX 檔案。Microsoft 希望 Razor 更智慧,讓開發人員的工作更容易。
讓我們來看一個 ASPX 檔案的示例程式碼,其中包含一些文字。這是我們的 HTML 標記。它還包含少量 C# 程式碼。
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.ActionLink("Edit", "Edit", new { id = item.ID })%> |
<%: Html.ActionLink("Details", "Details", new { id = item.ID }) %>|
<%: Html.ActionLink("Delete", "Delete", new { id = item.ID })%>
</td>
<td>
<%: item.Name %>
</td>
<td>
<%: String.Format("{0,g}", item.JoiningDate) %>
</td>
</tr>
<%}%>
但這些 Web 窗體基本上被 Microsoft 重新用於與早期版本的 MVC 協同工作,這意味著 ASPX 檔案從未與 MVC 完全匹配。
當你需要從 C# 程式碼切換回 HTML,以及從 HTML 程式碼切換回 C# 程式碼時,語法有點笨拙。IntelliSense 還會提示你執行在 MVC 專案中毫無意義的操作,例如向 ASPX 檢視新增輸出快取和使用者控制元件的指令。
現在看看這段程式碼,它產生相同的輸出,不同之處在於它使用了 Razor 語法。
@foreach (var item in Model) {
<tr>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
@Html.ActionLink("Details", "Details", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
<td>
@item.Name
</td>
<td>
@String.Format("{0,g}", item.JoiningDate)
</td>
</tr>
}
使用 Razor 語法,你可以使用“@”符號開始一段 C# 程式碼,Razor 解析器會自動切換到將此語句(此 foreach 語句)作為一段 C# 程式碼進行解析。
但是當我們完成 foreach 語句並有我們的左大括號時,我們可以從 C# 程式碼切換到 HTML,而無需在其中放置顯式標記,例如百分號和尖括號。
Razor 解析器足夠智慧,可以切換 C# 程式碼和 HTML,並在需要放置右大括號時再次從 HTML 切換回 C# 程式碼。如果你比較這兩個程式碼塊,我認為你會同意 Razor 版本更容易閱讀和編寫。
使用 Razor 建立檢視
讓我們建立一個新的 ASP.Net MVC 專案。
在名稱欄位中輸入專案名稱,然後單擊“確定”。
為簡便起見,選擇“空”選項,並在“新增資料夾和核心引用”部分選中 MVC 複選框,然後單擊“確定”。它將建立一個具有最少預定義內容的基本 MVC 專案。
Visual Studio 建立專案後,你將在“解決方案資源管理器”視窗中看到許多檔案和資料夾。由於我們是從空專案模板建立 ASP.Net MVC 專案,因此目前應用程式沒有任何內容可以執行。由於我們從空應用程式開始,甚至沒有一個控制器,讓我們新增一個 HomeController。
要新增控制器,請右鍵單擊解決方案資源管理器中的控制器資料夾,然後選擇“新增”→“控制器”。這將顯示“新增腳手架”對話方塊。
選擇**MVC 5 控制器 - 空**選項,然後單擊“新增”按鈕,然後將顯示“新增控制器”對話方塊。
將名稱設定為 HomeController,然後單擊“新增”按鈕。你將在 Controllers 資料夾中看到一個新的 C# 檔案“HomeController.cs”,它也將在 Visual Studio 中開啟以進行編輯。
右鍵單擊 Index 操作,然後選擇“新增檢視…”。
從“模板”下拉列表中選擇“空”,然後單擊“新增”按鈕。Visual Studio 將在**View/Home**資料夾中建立一個 Index.cshtml 檔案。
請注意,Razor 檢視具有 cshtml 副檔名。如果你使用 Visual Basic 構建 MVC 應用程式,它將是 VBHTML 副檔名。此檔案的頂部是一個程式碼塊,它顯式地將此 Layout 屬性設定為 null。
執行此應用程式時,你將看到空白網頁,因為我們是從空模板建立的檢視。
讓我們新增一些 C# 程式碼來使事情更有趣。要在 Razor 檢視中編寫一些 C# 程式碼,我們要做的第一件事是鍵入“@”符號,該符號告訴解析器它將執行程式碼中的某些操作。
讓我們建立一個 FOR 迴圈,在花括號內指定“@i”,這實際上是告訴 Razor 放置 i 的值。
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>Index</title>
</head>
<body>
<div>
@for (int index = 0; index < 12; index++){
<div>@index </div>
}
</div>
</body>
</html>
執行此應用程式,你將看到以下輸出。
ASP.NET MVC - 資料註解
DataAnnotations 用於配置你的模型類,這將突出顯示最常用的配置。DataAnnotations 也被許多 .NET 應用程式(例如 ASP.NET MVC)理解,這允許這些應用程式利用相同的註釋進行客戶端驗證。DataAnnotation 屬性覆蓋預設的 Code-First 約定。
**System.ComponentModel.DataAnnotations** 包括以下影響列的可空性或大小的屬性。
- Key
- Timestamp
- ConcurrencyCheck
- Required
- MinLength
- MaxLength
- StringLength
**System.ComponentModel.DataAnnotations.Schema** 名稱空間包括以下影響資料庫模式的屬性。
- Table
- Column
- Index
- ForeignKey
- NotMapped
- InverseProperty
Key
Entity Framework 依賴於每個實體都有一個它用於跟蹤實體的鍵值。Code First 依賴的一個約定是它如何暗示每個 Code First 類中的哪個屬性是鍵。
約定是查詢名為“Id”的屬性或一個組合了類名和“Id”的屬性,例如“StudentId”。該屬性將對映到資料庫中的主鍵列。Student、Course 和 Enrollment 類遵循此約定。
現在假設 Student 類使用 StdntID 而不是 ID。當 Code First 未找到與該約定匹配的屬性時,由於 Entity Framework 要求你必須擁有一個鍵屬性,因此它將丟擲異常。
你可以使用 key 註釋來指定哪個屬性用作 EntityKey。
讓我們看一下包含 StdntID 的 Student 類。它不遵循預設的 Code First 約定,因此為了處理這個問題,添加了 Key 屬性,這將使其成為主鍵。
public class Student{
[Key]
public int StdntID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
執行應用程式並在 SQL Server 資源管理器中檢視資料庫時,你將看到主鍵現在是 Students 表中的 StdntID。
Entity Framework 也支援複合鍵。複合鍵是由多個屬性組成的主鍵。例如,你有一個 DrivingLicense 類,其主鍵是 LicenseNumber 和 IssuingCountry 的組合。
public class DrivingLicense{
[Key, Column(Order = 1)]
public int LicenseNumber { get; set; }
[Key, Column(Order = 2)]
public string IssuingCountry { get; set; }
public DateTime Issued { get; set; }
public DateTime Expires { get; set; }
}
當你有複合鍵時,Entity Framework 要求你定義鍵屬性的順序。你可以使用 Column 註釋來指定順序。
Timestamp
Code First 將 Timestamp 屬性與 ConcurrencyCheck 屬性相同對待,但它還將確保 Code First 生成的資料庫欄位不可為空。
更常見的是使用 rowversion 或 timestamp 欄位進行併發檢查。但與其使用 ConcurrencyCheck 註釋,不如使用更具體的 TimeStamp 註釋,只要屬性的型別是位元組陣列即可。在一個給定的類中,你只能有一個 timestamp 屬性。
讓我們來看一個簡單的例子,透過向 Course 類新增 TimeStamp 屬性。
public class Course{
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
[Timestamp]
public byte[] TStamp { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
如上例所示,Timestamp 屬性應用於 Course 類的 Byte[] 屬性。因此,Code First 將在 Courses 表中建立一個 timestamp 列 TStamp。
ConcurrencyCheck
ConcurrencyCheck 註釋允許你標記一個或多個屬性,以便在使用者編輯或刪除實體時在資料庫中用於併發檢查。如果你一直在使用 EF 設計器,這與將屬性的 ConcurrencyMode 設定為 Fixed 一致。
讓我們來看一個簡單的例子,看看 ConcurrencyCheck 如何透過將其新增到 Course 類中的 Title 屬性來工作。
public class Course{
public int CourseID { get; set; }
[ConcurrencyCheck]
public string Title { get; set; }
public int Credits { get; set; }
[Timestamp, DataType("timestamp")]
public byte[] TimeStamp { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
在上例的 Course 類中,ConcurrencyCheck 屬性應用於現有的 Title 屬性。Code First 將在更新命令中包含 Title 列以檢查樂觀併發,如下面的程式碼所示。
exec sp_executesql N'UPDATE [dbo].[Courses] SET [Title] = @0 WHERE (([CourseID] = @1) AND ([Title] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0 = N'Maths',@1 = 1,@2 = N'Calculus' go
Required
Required 註釋告訴 EF 特定屬性是必需的。讓我們看看以下 Student 類,其中 Required id 已新增到 FirstMidName 屬性。Required 屬性將強制 EF 確保該屬性包含資料。
public class Student{
[Key]
public int StdntID { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
你可以在上面的 Student 類示例中看到 Required 屬性應用於 FirstMidName 和 LastName。因此,Code First 將在 Students 表中建立一個 NOT NULL FirstMidName 和 LastName 列,如下面的螢幕截圖所示。
MaxLength
MaxLength 屬性允許你指定其他屬性驗證。它可以應用於域類的字串或陣列型別屬性。EF Code First 將根據 MaxLength 屬性中指定的設定列的大小。
讓我們看一下下面的 Course 類,其中 MaxLength(24) 屬性應用於 Title 屬性。
public class Course{
public int CourseID { get; set; }
[ConcurrencyCheck]
[MaxLength(24)]
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
執行上述應用程式時,Code-First 將在 Coursed 表中建立一個 nvarchar(24) 列 Title,如下面的螢幕截圖所示。
現在,當用戶設定包含超過 24 個字元的 Title 時,EF 將丟擲 EntityValidationError。
MinLength
MinLength 屬性允許你指定其他屬性驗證,就像你對 MaxLength 所做的那樣。MinLength 屬性也可以與 MaxLength 屬性一起使用,如下面的程式碼所示。
public class Course{
public int CourseID { get; set; }
[ConcurrencyCheck]
[MaxLength(24) , MinLength(5)]
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
如果將 Title 屬性的值設定為小於 MinLength 屬性中指定的長度或大於 MaxLength 屬性中指定的長度,EF 將丟擲 EntityValidationError。
StringLength
StringLength 屬性還允許您指定其他屬性驗證,例如 MaxLength。不同之處在於 StringLength 屬性只能應用於域類的字串型別屬性。
public class Course{
public int CourseID { get; set; }
[StringLength (24)]
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
Entity Framework 也驗證 StringLength 屬性的屬性值。現在,如果使用者設定的標題包含超過 24 個字元,則 EF 將丟擲 EntityValidationError。
Table
預設的 Code First 約定會建立與類名相同的表名。如果您讓 Code First 建立資料庫,您也可以更改它正在建立的表的名稱。您可以將 Code First 與現有資料庫一起使用。但並非總是類名與資料庫中表名匹配的情況。
Table 屬性會覆蓋此預設約定。對於給定的域類,EF Code First 將使用 Table 屬性中指定的名稱建立一個表。
讓我們來看一個例子,其中類名為 Student,根據約定,Code First 假設這將對映到名為 Students 的表。如果不是這種情況,您可以使用 Table 屬性指定表名,如下面的程式碼所示。
[Table("StudentsInfo")]
public class Student{
[Key]
public int StdntID { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
您現在可以看到 Table 屬性將表指定為 StudentsInfo。生成表時,您將看到表名 StudentsInfo,如下面的螢幕截圖所示。
您不僅可以指定表名,還可以使用 Table 屬性指定表的架構,如下面的程式碼所示。
[Table("StudentsInfo", Schema = "Admin")]
public class Student{
[Key]
public int StdntID { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
在上面的示例中,表使用 admin 架構指定。現在 Code First 將在 Admin 架構中建立 StudentsInfo 表,如下面的螢幕截圖所示。
Column
它也與 Table 屬性相同,但 Table 屬性會覆蓋錶行為,而 Column 屬性會覆蓋列行為。預設的 Code First 約定會建立與屬性名相同的列名。
如果您讓 Code First 建立資料庫,並且您還想更改表中列的名稱。Column 屬性會覆蓋此預設約定。對於給定的屬性,EF Code First 將使用 Column 屬性中指定的名稱建立一個列。
讓我們再次來看下面的示例,其中屬性名為 FirstMidName,根據約定,Code First 假設這將對映到名為 FirstMidName 的列。如果不是這種情況,您可以使用 Column 屬性指定列名,如下面的程式碼所示。
public class Student{
public int ID { get; set; }
public string LastName { get; set; }
[Column("FirstName")]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
您現在可以看到 Column 屬性將列指定為 FirstName。生成表時,您將看到列名 FirstName,如下面的螢幕截圖所示。
Index
Index 屬性是在 Entity Framework 6.1 中引入的。**注意** - 如果你使用的是早期版本,本節中的資訊不適用。
您可以使用 IndexAttribute 在一個或多個列上建立索引。將屬性新增到一個或多個屬性將導致 EF 在建立資料庫時在資料庫中建立相應的索引。
在大多數情況下,索引可以使資料檢索更快、更高效。但是,使用索引過度載入表或檢視可能會對其他操作(例如插入或更新)的效能產生不利影響。
**索引** 是 Entity Framework 中的新功能,您可以透過減少從資料庫查詢資料所需的時間來提高 Code First 應用程式的效能。
您可以使用 Index 屬性向資料庫新增索引,並覆蓋預設的 Unique 和 Clustered 設定以獲得最適合您方案的索引。預設情況下,索引將命名為 IX_<屬性名>
讓我們來看下面的程式碼,其中在 Course 類中為 Credits 添加了 Index 屬性。
public class Cours{
public int CourseID { get; set; }
public string Title { get; set; }
[Index]
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
您可以看到 Index 屬性應用於 Credits 屬性。現在生成表時,您將在索引中看到 IX_Credits。
預設情況下,索引是非唯一的,但您可以使用**IsUnique**命名引數指定索引應該是唯一的。以下示例介紹了一個唯一索引,如下面的程式碼所示。
public class Course{
public int CourseID { get; set; }
[Index(IsUnique = true)]
public string Title { get; set; }
[Index]
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ForeignKey
Code First 約定將處理模型中最常見的關聯,但在某些情況下需要幫助。例如,更改 Student 類中主鍵的名稱會導致與其與 Enrollment 類之間的關聯出現問題。
public class Enrollment{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }
public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
public class Student{
[Key]
public int StdntID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
在生成資料庫時,Code First 會看到 Enrollment 類中的 StudentID 屬性,並根據約定(它與類名加“ID”匹配)將其識別為對 Student 類的外部索引鍵。但是 Student 類中沒有 StudentID 屬性,而是 Student 類中的 StdntID 屬性。
解決方法是在 Enrollment 中建立一個導航屬性,並使用 ForeignKey DataAnnotation 來幫助 Code First 理解如何在兩個類之間建立關聯,如下面的程式碼所示。
public class Enrollment{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }
public virtual Course Course { get; set; }
[ForeignKey("StudentID")]
public virtual Student Student { get; set; }
}
您現在可以看到 ForeignKey 屬性已應用於導航屬性。
NotMapped
根據 Code First 的預設約定,每個具有受支援資料型別幷包含 getter 和 setter 的屬性都將在資料庫中表示。但這並非應用程式中的始終如此。NotMapped 屬性會覆蓋此預設約定。例如,您可能在 Student 類中有一個屬性,例如 FatherName,但它不需要儲存。您可以將 NotMapped 屬性應用於 FatherName 屬性,您不希望在資料庫中為此屬性建立列。以下是程式碼。
public class Student{
[Key]
public int StdntID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
[NotMapped]
public int FatherName { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
您可以看到 NotMapped 屬性已應用於 FatherName 屬性。現在生成表時,您將看到 FatherName 列不會在資料庫中建立,但它存在於 Student 類中。
對於沒有 getter 或 setter 的屬性,Code First 不會建立列。
InverseProperty
當您在類之間有多個關係時,使用 InverseProperty。在 Enrollment 類中,您可能希望跟蹤誰註冊了 Current Course 和誰註冊了 Previous Course。
讓我們為 Enrollment 類新增兩個導航屬性。
public class Enrollment{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }
public virtual Course CurrCourse { get; set; }
public virtual Course PrevCourse { get; set; }
public virtual Student Student { get; set; }
}
同樣,您還需要在這些屬性引用的 Course 類中新增內容。Course 類具有返回 Enrollment 類的導航屬性,其中包含所有當前和以前的註冊資訊。
public class Course{
public int CourseID { get; set; }
public string Title { get; set; }
[Index]
public int Credits { get; set; }
public virtual ICollection<Enrollment> CurrEnrollments { get; set; }
public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
}
如果外部索引鍵屬性未包含在特定類中,則 Code First 會建立 {類名} _{主鍵} 外部索引鍵列,如上面的類所示。生成資料庫時,您將看到許多外部索引鍵,如下面的螢幕截圖所示。
您可以看到 Code First 無法自行匹配兩個類中的屬性。Enrollments 的資料庫表應該有一個 CurrCourse 的外部索引鍵和一個 PrevCourse 的外部索引鍵,但是 Code First 將建立四個外部索引鍵屬性,即:
- CurrCourse_CourseID
- PrevCourse_CourseID
- Course_CourseID
- Course_CourseID1
要解決這些問題,您可以使用 InverseProperty 註釋來指定屬性的對齊方式。
public class Course{
public int CourseID { get; set; }
public string Title { get; set; }
[Index]
public int Credits { get; set; }
[InverseProperty("CurrCourse")]
public virtual ICollection<Enrollment> CurrEnrollments { get; set; }
[InverseProperty("PrevCourse")]
public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
}
如您現在所見,當在上面的 Course 類中應用 InverseProperty 屬性時,透過指定它屬於 Enrollment 類的哪個引用屬性,Code First 將生成資料庫並在 Enrollments 表中僅建立兩個外部索引鍵列,如下面的螢幕截圖所示。
我們建議您執行上述示例以更好地理解。
ASP.NET MVC - NuGet 包管理
在本章中,我們將討論 NuGet,它是 .NET 和 Visual Studio 的包管理器。NuGet 可用於查詢和安裝包,即您希望在專案中使用的軟體部件、程式集和內容。
NuGet 不是特定於 ASP.NET MVC 專案的工具。這是一個可以在 Visual Studio 中用於控制檯應用程式、WPF 應用程式、Azure 應用程式以及任何型別應用程式的工具。
包管理
NuGet 是一個包管理器,負責下載、安裝、更新和配置系統中的軟體。軟體這個詞並不意味著像 Microsoft Word 或 Notepad 2 等終端使用者軟體,而是指您希望在專案中使用的軟體部件、程式集引用。
例如,您可能想要使用的程式集可能是用於模擬物件單元測試的模擬程式集,或者用於資料訪問的 NHibernate,以及您在構建應用程式時使用的元件。上述元件是開源軟體,但您可以找到一些 NuGet 包是閉源軟體。您找到的一些包甚至是由 Microsoft 生產的。
上述所有包(如模擬和 NHibernate 以及 Microsoft 包,例如 Entity Framework 的預覽版)的共同點是它們預設情況下不包含在 Visual Studio 中。
沒有 NuGet
要安裝任何這些元件而無需 NuGet,您需要執行以下步驟。
如果您想使用其中一個元件,您需要找到某個特定專案的首頁並查詢下載連結。然後,下載專案後,它通常以 ZIP 格式存在,因此您需要解壓縮它。
如果您沒有下載二進位制檔案,則首先需要構建軟體,然後在專案中引用它。此時,許多元件仍然需要一些配置才能啟動和執行。
使用 NuGet
NuGet 替換了前面討論的所有步驟,您只需要說“新增包”。NuGet 知道在哪裡下載最新版本,知道如何解壓縮它,如何建立對該元件的引用,甚至如何配置它。這可以讓您有更多時間來構建軟體。
讓我們來看一個簡單的示例,我們將使用 NuGet 在 ASP.NET MVC 專案中新增對 Entity Framework 的支援。
**步驟 1** - 安裝 Entity Framework。右鍵單擊專案並選擇 NuGet 包管理器→管理 NuGet 包解決方案…
它將開啟 NuGet 包管理器。
**步驟 2** - 在搜尋框中搜索 Entity framework。
**步驟 3** - 選擇 Entity Framework 並單擊“安裝”按鈕。它將開啟預覽對話方塊。
**步驟 4** - 單擊“確定”繼續。
**步驟 5** - 單擊“我接受”按鈕開始安裝。
安裝 Entity Framework 後,您將在輸出視窗中看到訊息,如上所示。
使用 NuGet 安裝包時,您會在託管專案的解決方案檔案所在的同一資料夾中看到一個新的 packages 目錄。此 packages 目錄包含您為該解決方案中的任何專案安裝的所有包。
換句話說,NuGet 不會將包下載到中心位置,而是基於每個解決方案進行儲存。
ASP.NET MVC - Web API
ASP.NET Web API 是一個框架,它使構建可訪問各種客戶端(包括瀏覽器和移動裝置)的 HTTP 服務變得容易。ASP.NET Web API 是在 .NET Framework 上構建 RESTful 應用程式的理想平臺。
在 Web 上構建 API 時,您可以透過多種方式構建 Web 上的 API。這些包括 HTTP/RPC,這意味著使用 HTTP 在遠端過程呼叫中呼叫 Web 上的內容,例如方法。
動詞本身包含在 API 中,例如獲取客戶、插入發票、刪除客戶,並且這些端點中的每一個最終都是一個單獨的 URI。
讓我們透過建立一個新的 ASP.NET Web 應用程式來看一個 Web API 的簡單示例。
步驟 1 - 開啟 Visual Studio 並單擊檔案 → 新建 → 專案選單選項。
將開啟一個新的專案對話方塊。
步驟2 - 從左窗格中選擇“模板”→“Visual C#”→“Web”。
**步驟 3** - 在中間窗格中,選擇 ASP.NET Web 應用程式
在“名稱”欄位中輸入專案名稱 WebAPIDemo,然後單擊“確定”繼續。您將看到以下對話方塊,該對話方塊要求您設定 ASP.NET 專案的初始內容。
步驟 4 − 為簡化操作,選擇“Empty”選項,並在“Add folders and core references for”部分選中“Web API”複選框,然後單擊“Ok”。
步驟 5 − 這將建立一個具有最少預定義內容的基本 MVC 專案。
Visual Studio建立專案後,您將在解決方案資源管理器視窗中看到許多檔案和資料夾。
步驟 6 − 現在我們需要新增一個模型。在解決方案資源管理器中右鍵單擊“Models”資料夾,然後選擇“Add”→“Class”。
現在您將看到“新增新項”對話方塊。
步驟 7 − 在中間面板中選擇“Class”,並在名稱欄位中輸入“Employee.cs”。
步驟 8 − 使用以下程式碼向 Employee 類新增一些屬性。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebAPIDemo.Models {
public class Employee{
public int ID { get; set; }
public string Name { get; set; }
public DateTime JoiningDate { get; set; }
public int Age { get; set; }
}
}
步驟 9 − 讓我們新增控制器。在解決方案資源管理器中右鍵單擊“Controllers”資料夾,然後選擇“Add”→“Controller”。
它將顯示“新增腳手架”對話方塊。
步驟 10 − 選擇“Web API 2 Controller - Empty”選項。此模板將為控制器建立一個帶有預設操作的 Index 方法。
步驟 11 − 單擊“Add”按鈕,將出現“新增控制器”對話方塊。
步驟 12 − 將名稱設定為“EmployeesController”,然後單擊“Add”按鈕。
您將在“Controllers”資料夾中看到一個新的 C# 檔案“EmployeeController.cs”,它在 Visual Studio 中開啟以進行編輯,其中包含一些預設操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using WebAPIDemo.Models;
namespace WebAPIDemo.Controllers{
public class EmployeesController : ApiController{
Employee[] employees = new Employee[]{
new Employee { ID = 1, Name = "Mark", JoiningDate =
DateTime.Parse(DateTime.Today.ToString()), Age = 30 },
new Employee { ID = 2, Name = "Allan", JoiningDate =
DateTime.Parse(DateTime.Today.ToString()), Age = 35 },
new Employee { ID = 3, Name = "Johny", JoiningDate =
DateTime.Parse(DateTime.Today.ToString()), Age = 21 }
};
public IEnumerable<Employee> GetAllEmployees(){
return employees;
}
public IHttpActionResult GetEmployee(int id){
var employee = employees.FirstOrDefault((p) => p.ID == id);
if (employee == null){
return NotFound();
}
return Ok(employee);
}
}
}
步驟 13 − 執行此應用程式,並在 URL 末尾指定“/api/employees/”,然後按“Enter”。您將看到以下輸出。
步驟 14 − 讓我們指定以下 URL https://:63457/api/employees/1,您將看到以下輸出。
ASP.NET MVC - 腳手架
ASP.NET Scaffolding 是一個用於 ASP.NET Web 應用程式的程式碼生成框架。Visual Studio 2013 包括為 MVC 和 Web API 專案預安裝的程式碼生成器。當您想要快速新增與資料模型互動的程式碼時,可以將 scaffolding 新增到您的專案中。使用 scaffolding 可以減少開發專案中標準資料操作所需的時間。
正如您所看到的,我們已經為 Index、Create、Edit 操作建立了檢視,並且還需要更新操作方法。但是 ASP.Net MVC 提供了一種更簡單的方法來使用 scaffolding 建立所有這些檢視和操作方法。
讓我們來看一個簡單的例子。我們將建立一個包含 Employee 模型類的相同示例,但這次我們將使用 scaffolding。
**步驟1** - 開啟Visual Studio,然後單擊“檔案”→“新建”→“專案”選單選項。
將開啟一個新的專案對話方塊。
步驟2 - 從左窗格中選擇“模板”→“Visual C#”→“Web”。
步驟3 - 在中間窗格中,選擇ASP.NET Web應用程式。
步驟 4 − 在“Name”欄位中輸入專案名稱“MVCScaffoldingDemo”,然後單擊“Ok”繼續。您將看到以下對話方塊,要求您設定 ASP.NET 專案的初始內容。
步驟 5 − 為簡化操作,選擇“Empty”選項,並在“Add folders and core references for”部分選中“MVC”複選框,然後單擊“Ok”。
它將建立一個具有最少預定義內容的基本MVC專案。
Visual Studio建立專案後,您將在解決方案資源管理器視窗中看到許多檔案和資料夾。
新增 Entity Framework 支援
第一步是安裝 Entity Framework。右鍵單擊專案,然後選擇“NuGet Package Manager”→“Manage NuGet Packages for Solution…”。
這將開啟“NuGet Package Manager”。在搜尋框中搜索 Entity framework。
選擇實體框架並點選“安裝”按鈕。它將開啟預覽對話方塊。
點選確定繼續。
單擊“I Accept”按鈕開始安裝。
安裝 Entity Framework 後,您將在輸出視窗中看到如下所示的訊息。
新增模型
要新增模型,請在解決方案資源管理器中右鍵單擊“Models”資料夾,然後選擇“Add”→“Class”。您將看到“新增新項”對話方塊。
在中間面板中選擇“Class”,並在名稱欄位中輸入“Employee.cs”。
使用以下程式碼向 Employee 類新增一些屬性。
using System;
namespace MVCScaffoldingDemo.Models {
public class Employee{
public int ID { get; set; }
public string Name { get; set; }
public DateTime JoiningDate { get; set; }
public int Age { get; set; }
}
}
新增DBContext
我們有一個 Employee 模型,現在我們需要新增另一個類,它將與 Entity Framework 通訊以檢索和儲存資料。以下是 Employee.cs 檔案中的完整程式碼。
using System;
using System.Data.Entity;
namespace MVCScaffoldingDemo.Models{
public class Employee{
public int ID { get; set; }
public string Name { get; set; }
public DateTime JoiningDate { get; set; }
public int Age { get; set; }
}
public class EmpDBContext : DbContext{
public DbSet<Employee> Employees { get; set; }
}
}
如您所見,“EmpDBContext”派生自一個名為“DbContext”的 EF 類。在這個類中,我們有一個名為 DbSet 的屬性,它基本上代表您想要查詢和儲存的實體。
現在讓我們構建一個解決方案,您將在專案成功構建時看到訊息。
新增 Scaffolding 項
要新增 scaffolding,請在解決方案資源管理器中右鍵單擊“Controllers”資料夾,然後選擇“Add”→“New Scaffolded Item”。
它將顯示“新增腳手架”對話方塊。
在中間面板中選擇“MVC 5 Controller with views, using Entity Framework”,然後單擊“Add”按鈕,這將顯示“新增控制器”對話方塊。
從“Model class”下拉列表中選擇“Employee”,從“Data context class”下拉列表中選擇“EmpDBContext”。您還會看到控制器名稱已預設選中。
單擊“Add”按鈕繼續,您將在 EmployeesController 中看到以下程式碼,該程式碼是由 Visual Studio 使用 Scaffolding 建立的。
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using MVCScaffoldingDemo.Models;
namespace MVCScaffoldingDemo.Controllers {
public class EmployeesController : Controller{
private EmpDBContext db = new EmpDBContext();
// GET: Employees
public ActionResult Index(){
return View(db.Employees.ToList());
}
// GET: Employees/Details/5
public ActionResult Details(int? id){
if (id == null){
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Employee employee = db.Employees.Find(id);
if (employee == null){
return HttpNotFound();
}
return View(employee);
}
// GET: Employees/Create
public ActionResult Create(){
return View();
}
// POST: Employees/Create
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Name,JoiningDate,Age")]
Employee employee){
if (ModelState.IsValid){
db.Employees.Add(employee);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
// GET: Employees/Edit/5
public ActionResult Edit(int? id){
if (id == null){
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Employee employee = db.Employees.Find(id);
if (employee == null){
return HttpNotFound();
}
return View(employee);
}
// POST: Employees/Edit/5
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,Name,JoiningDate,Age")]Employee employee){
if (ModelState.IsValid){
db.Entry(employee).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
// GET: Employees/Delete/5
public ActionResult Delete(int? id){
if (id == null){
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Employee employee = db.Employees.Find(id);
if (employee == null){
return HttpNotFound();
}
return View(employee);
}
// POST: Employees/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id){
Employee employee = db.Employees.Find(id);
db.Employees.Remove(employee);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing){
if (disposing){
db.Dispose();
}
base.Dispose(disposing);
}
}
}
執行您的應用程式並指定以下 URL https://:59359/employees。您將看到以下輸出。
您可以看到 View 中沒有資料,因為我們尚未向 Visual Studio 建立的資料庫中新增任何記錄。
讓我們透過單擊“建立新”連結從瀏覽器新增一條記錄,它將顯示“建立”檢視。
讓我們在以下欄位中新增一些資料。
單擊“建立”按鈕,它將更新 Index 檢視。
您可以看到新記錄也已新增到資料庫中。
如您所見,我們已經使用 Scaffolding 實現了相同的示例,這是一種更簡單的方法,可以根據您的模型類建立檢視和操作方法。
ASP.NET MVC - Bootstrap
在本章中,我們將介紹 Bootstrap,它是一個現在包含在 ASP.NET 和 MVC 中的前端框架。它是一個流行的 Web 應用程式前端工具包,將幫助您使用 HTML、CSS 和 JavaScript 構建使用者介面。
它最初是由 Twitter 的 Web 開發人員為個人使用而建立的,但是,它現在是開源的,並且由於其靈活性和易用性而受到設計師和開發人員的歡迎。
您可以使用 Bootstrap 建立一個在大型桌面顯示器到小型移動螢幕上的所有裝置上看起來都很好的介面。在本章中,我們還將瞭解 Bootstrap 如何與您的佈局檢視一起使用以構建應用程式的外觀。
Bootstrap 提供了佈局、按鈕、表單、選單、視窗小部件、圖片輪播、標籤、徽章、排版和各種功能所需的所有元件。由於 Bootstrap 全部都是 HTML、CSS 和 JavaScript(所有開放標準),因此您可以將其與任何框架一起使用,包括 ASP.NET MVC。當您啟動一個新的 MVC 專案時,Bootstrap 將存在,這意味著您將在專案中找到 Bootstrap.css 和 Bootstrap.js。
讓我們建立一個新的 ASP.NET Web 應用程式。
輸入專案名稱,例如“MVCBootstrap”,然後單擊“Ok”。您將看到以下對話方塊。
在此對話方塊中,如果您選擇空模板,您將獲得一個空的 Web 應用程式,並且不會存在 Bootstrap。也不會出現任何控制器或任何其他指令碼檔案。
現在選擇 MVC 模板並單擊“Ok”。當 Visual Studio 建立此解決方案時,它將下載並安裝到專案中的一個包將是 Bootstrap NuGet 包。您可以透過轉到 packages.config 來驗證,您可以在其中看到 Bootstrap 版本 3 包。
您還可以看到包含不同 css 檔案的 Content 資料夾。
執行此應用程式,您將看到以下頁面。
當此頁面出現時,您看到的大部分佈局和樣式都是 Bootstrap 應用的佈局和樣式。它包括頂部的導航欄以及連結,以及宣傳 ASP.NET 的顯示。它還包括所有這些關於入門和獲取更多庫和 Web 託管的片段。
如果您稍微擴大瀏覽器,它們實際上將並排顯示,這是 Bootstrap 響應式設計功能的一部分。
如果您檢視 Content 資料夾,您將找到 Bootstrap.css 檔案。
NuGet 包還提供了該檔案的一個縮小版本,該版本略小一些。在 scripts 下,您將找到 Bootstrap.js,這是 Bootstrap 的某些元件所必需的。
它確實依賴於 jQuery,幸運的是 jQuery 也安裝在此專案中,並且有一個 Bootstrap JavaScript 檔案的縮小版本。
現在問題是,所有這些都在應用程式中的哪裡新增?您可能期望它位於佈局模板中,此專案的佈局檢視位於 View/Shared/_layout.cshtml 下。
佈局檢視控制 UI 的結構。以下是 _layout.cshtml 檔案中的完整程式碼。
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8" />
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class = "navbar navbar-inverse navbar-fixed-top">
<div class = "container">
<div class = "navbar-header">
<button type = "button" class = "navbar-toggle" datatoggle =
"collapse" data-target = ".navbar-collapse">
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new
{ area = "" }, new { @class = "navbar-brand" })
</div>
<div class = "navbar-collapse collapse">
<ul class = "nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class = "container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
在上面的程式碼中,需要注意兩點。首先,在 <title> 之後,您將看到以下程式碼行。
@Styles.Render("~/Content/css")
用於 Content/css 的 Styles.Render 實際上是包含 Bootstrap.css 檔案的位置,在底部,您將看到以下程式碼行。
@Scripts.Render("~/bundles/bootstrap")
它正在呈現 Bootstrap 指令碼。因此,為了找出這些捆綁包中究竟包含什麼,我們必須進入 BundleConfig 檔案,該檔案位於 App_Start 資料夾中。
在 BundleConfig 中,您可以看到底部 CSS 捆綁包同時包含 Bootstrap.css 和我們自定義的 site.css。
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
這是一個我們可以新增自己的樣式表以自定義應用程式外觀的地方。您還可以看到 Bootstrap 捆綁包出現在 CSS 捆綁包之前,該捆綁包包括 Bootstrap.js 和另一個 JavaScript 檔案 respond.js。
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
讓我們註釋掉 Bootstrap.css,如下面的程式碼所示。
bundles.Add(new StyleBundle("~/Content/css").Include(
//"~/Content/bootstrap.css",
"~/Content/site.css"));
再次執行此應用程式,讓您瞭解 Bootstrap 的作用,因為現在唯一可用的樣式是 site.css 中的樣式。
如您所見,我們丟失了佈局,頁面頂部的導航欄。現在一切看起來都很普通和乏味。
現在讓我們看看 Bootstrap 的全部內容。Bootstrap 自動執行幾件事,當您新增類並具有正確的 HTML 結構時,Bootstrap 可以為您執行幾件事。如果您檢視 _layout.cshtml 檔案,您將看到 navbar 類,如下面的程式碼所示。
<div class = "navbar navbar-inverse navbar-fixed-top">
<div class = "container">
<div class = "navbar-header">
<button type = "button" class = "navbar-toggle" datatoggle =
"collapse" data-target = ".navbar-collapse">
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
</button>
<a class = "navbar-brand" href = "/">Application name</a>
</div>
<div class = "navbar-collapse collapse">
<ul class = "nav navbar-nav">
<li><a href = "/">Home</a></li>
<li><a href = "/Home/About">About</a></li>
<li><a href = "/Home/Contact">Contact</a></li>
</ul>
<ul class = "nav navbar-nav navbar-right">
<li><a href = "/Account/Register" id = "registerLink">Register</a></li>
<li><a href = "/Account/Login" id = "loginLink">Log in</a></li>
</ul>
</div>
</div>
</div>
它是來自 Bootstrap 的 CSS 類,例如 navbar、navbar inverse 和 navbar fixed top。如果您刪除其中一些類,例如 navbar inverse、navbar fixed top,並且還取消註釋 Bootstrap.css,然後再次執行您的應用程式,您將看到以下輸出。
您將看到我們仍然有一個導航欄,但現在它沒有使用反向顏色,所以它是白色的。它也不會粘在頁面的頂部。當您向下滾動時,導航欄會從頂部滾動,您將再也看不到它。
ASP.NET MVC - 單元測試
在計算機程式設計中,單元測試是一種軟體測試方法,透過該方法測試單個原始碼單元以確定它們是否適合使用。換句話說,它是一種軟體開發過程,其中應用程式中最小的可測試部分(稱為單元)被單獨且獨立地仔細檢查其是否正常執行。
在程序式程式設計中,一個單元可以是整個模組,但更常見的是單個函式或過程。在面向物件程式設計中,一個單元通常是整個介面,例如一個類,但也可能是一個單獨的方法。
單元測試通常是自動化的,但也可以手動進行。
單元測試的目標
單元測試的主要目標是獲取應用程式中最小的可測試軟體單元,並確定其行為是否完全符合預期。在將各個單元整合到模組中以測試模組間的介面之前,需要分別測試每個單元。
讓我們來看一個簡單的單元測試示例,在這個示例中,我們將建立一個新的帶有單元測試的 ASP.NET MVC 應用程式。
步驟 1 - 開啟 Visual Studio 並單擊檔案 → 新建 → 專案選單選項。
將開啟一個新的專案對話方塊。
步驟 2 − 從左側面板中,選擇模板 > Visual C# > Web。
步驟3 - 在中間窗格中,選擇ASP.NET Web應用程式。
步驟 4 − 在“名稱”欄位中輸入專案名稱“MVCUnitTestingDemo”,然後單擊“確定”繼續。您將看到以下對話方塊,要求您設定 ASP.NET 專案的初始內容。
步驟 5 − 選擇 MVC 作為模板,並且不要忘記選中對話方塊底部的“新增單元測試”複選框。您也可以更改測試專案名稱,但在本例中,我們保留預設名稱。
Visual Studio建立專案後,您將在解決方案資源管理器視窗中看到許多檔案和資料夾。
步驟 6 − 您可以在解決方案資源管理器中看到兩個專案。一個是 ASP.NET Web 專案,另一個是單元測試專案。
步驟 7 − 執行此應用程式,您將看到以下輸出。
如上圖所示,導航欄上有“主頁”、“關於”和“聯絡”按鈕。讓我們選擇“關於”,您將看到以下檢視。
讓我們選擇“聯絡”,以下螢幕將彈出。
現在讓我們展開“MVCUnitTestingDemo”專案,您將在“Controllers”資料夾下看到 HomeController.cs 檔案。
HomeController 包含三個操作方法,如下面的程式碼所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCUnitTestingDemo.Controllers {
public class HomeController : Controller{
public ActionResult Index(){
return View();
}
public ActionResult About(){
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact(){
ViewBag.Message = "Your contact page.";
return View();
}
}
}
讓我們展開MVCUnitTestingDemo.Tests專案,您將在“Controllers”資料夾下看到 HomeControllerTest.cs 檔案。
在這個 HomeControllerTest 類中,您將看到三個方法,如下面的程式碼所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MVCUnitTestingDemo;
using MVCUnitTestingDemo.Controllers;
namespace MVCUnitTestingDemo.Tests.Controllers{
[TestClass]
public class HomeControllerTest{
[TestMethod]
public void Index(){
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
[TestMethod]
public void About(){
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.About() as ViewResult;
// Assert
Assert.AreEqual("Your application description page.", result.ViewBag.Message);
}
[TestMethod]
public void Contact(){
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Contact() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
}
}
這三個方法將測試 Index、About 和 Contact 操作方法是否正常工作。要測試這三個操作方法,請轉到“測試”選單。
選擇“執行”→“所有測試”來測試這些操作方法。
現在,您將在左側看到測試資源管理器,其中您可以看到所有測試都已透過。讓我們再新增一個操作方法,該方法將列出所有員工。首先,我們需要在 Models 資料夾中新增一個員工類。
以下是 Employee 類的實現。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MVCUnitTestingDemo.Models{
public class Employee{
public int ID { get; set; }
public string Name { get; set; }
public DateTime JoiningDate { get; set; }
public int Age { get; set; }
}
}
我們需要新增 EmployeeController。右鍵單擊解決方案資源管理器中的控制器資料夾,然後選擇“新增”→“控制器”。
它將顯示“新增腳手架”對話方塊。
選擇 MVC 5 Controller – Empty 選項,然後單擊“新增”按鈕,將出現“新增控制器”對話方塊。
將名稱設定為 EmployeeController 並單擊“新增”按鈕。
您將在“Controllers”資料夾中看到一個新的 C# 檔案“EmployeeController.cs”,該檔案可在 Visual Studio 中開啟進行編輯。讓我們使用以下程式碼更新 EmployeeController。
using MVCUnitTestingDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCUnitTestingDemo.Controllers {
public class EmployeeController : Controller{
[NonAction]
public List<Employee> GetEmployeeList(){
return new List<Employee>{
new Employee{
ID = 1,
Name = "Allan",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 23
},
new Employee{
ID = 2,
Name = "Carson",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 45
},
new Employee{
ID = 3,
Name = "Carson",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 37
},
new Employee{
ID = 4,
Name = "Laura",
JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
Age = 26
},
};
}
// GET: Employee
public ActionResult Index(){
return View();
}
public ActionResult Employees(){
var employees = from e in GetEmployeeList()
orderby e.ID
select e;
return View(employees);
}
}
}
要為 Employees 操作方法新增檢視,請右鍵單擊 Employees 操作並選擇“新增檢視…”。
您將看到檢視的預設名稱。從“模板”下拉列表中選擇“列表”,從“模型類”下拉列表中選擇“Employee”,然後單擊“確定”。
現在我們需要新增員工列表連結,讓我們開啟位於 Views/Shared 資料夾下的 _layout.cshtml 檔案,並在“聯絡”連結下方新增員工列表的連結。
<li>@Html.ActionLink("Employees List", "Employees", "Employee")</li>
以下是 _layout.cshtml 的完整實現。
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8" />
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class = "navbar navbar-inverse navbar-fixed-top">
<div class = "container">
<div class = "navbar-header">
<button type = "button" class = "navbar-toggle" datatoggle =
"collapse" data-target = ".navbar-collapse">
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
<span class = "icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new
{ area = "" }, new { @class = "navbar-brand" })
</div>
<div class = "navbar-collapse collapse">
<ul class = "nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
<li>@Html.ActionLink("Employees List", "Employees", "Employee")</li>
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class = "container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
要測試 Employee 控制器中的 Employees 操作方法,我們需要在單元測試專案中新增另一個測試方法。以下是 EmployeeControllerTest 類,我們將在其中測試 Employees 操作方法。
[TestClass]
public class EmployeeControllerTest{
[TestMethod]
public void Employees(){
// Arrange
EmployeeController controller = new EmployeeController();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
}
從“測試”選單中選擇“執行”→“所有測試”來測試這些操作方法。
您可以看到 Employees 測試方法現在也已透過。執行應用程式後,您將看到以下輸出。
單擊導航欄中的“員工列表”選項,您將看到員工列表。
ASP.NET MVC - 部署
在本章中,我們將介紹如何部署 ASP.NET MVC 應用程式。在理解 ASP.NET MVC 應用程式中的不同概念之後,現在是時候瞭解部署過程了。因此,每當我們構建任何 MVC 應用程式時,我們實際上都會生成一個與其關聯的dll檔案,其中包含所有應用程式設定和邏輯,這些dll位於專案的 bin 目錄中,如下面的螢幕截圖所示。
釋出到 Microsoft Azure
讓我們來看一個簡單的示例,我們將在此示例中將我們的示例部署到 Microsoft Azure。
步驟 1 − 右鍵單擊解決方案資源管理器中的專案,然後選擇“釋出”,如下面的螢幕截圖所示。
步驟 2 − 您將看到“釋出 Web”對話方塊。單擊“Microsoft Azure Web 應用”。
它將顯示“登入”頁面。
步驟 3 − 輸入 Microsoft Azure 訂閱的憑據。
成功連線到您的 Azure 帳戶後,您將看到以下對話方塊。
步驟 4 − 單擊“新建”按鈕。
步驟 5 − 在上面的對話方塊中輸入所需的資訊,例如 Web 應用名稱(必須是唯一名稱)。您還需要輸入應用服務計劃、資源組,然後選擇您的區域。
步驟 6 − 單擊“下一步”按鈕繼續。
步驟 7 − 單擊省略號“…”以選擇連線字串。
步驟 8 − 選擇伺服器名稱,然後選擇 Windows 身份驗證選項。也選擇資料庫名稱。現在您將看到系統為您生成的連線字串。
步驟 9 − 單擊“下一步”繼續。
步驟 10 − 要檢查我們將釋出到 Azure 的所有檔案和 dll,請單擊“啟動預覽”。單擊“釋出”按鈕以釋出您的應用程式。
應用程式成功釋出到 Azure 後,您將在輸出視窗中看到訊息。
步驟 11 − 現在開啟您的瀏覽器並輸入以下 URL “http://mymvcdemoapp.azurewebsites.net/employees”,您將看到員工列表。
步驟 12 − 現在,如果您轉到您的 Azure 門戶並單擊“應用服務”,您將看到您的應用程式已部署到 Azure。
步驟 13 − 單擊您的應用的名稱,您將看到與該應用程式相關的各種資訊,例如 URL、狀態、位置等。
到目前為止,我們已經瞭解瞭如何在建立應用程式後將 Web 應用程式釋出到 Azure 應用。您還可以建立將部署到 Azure 的應用程式。
讓我們建立一個新的 ASP.NET MVC 應用程式。
步驟 1 − 單擊“確定”,您將看到以下對話方塊。
步驟 2 − 選擇 MVC 模板,並選中“在雲中託管”複選框。單擊“確定”。
當出現“配置 Microsoft Azure Web 應用設定”對話方塊時,請確保您已登入到 Azure。
您可以看到預設名稱,但您也可以更改Web 應用名稱。
步驟 3 − 輸入所需的資訊,如下面的螢幕截圖所示。
步驟 4 − 從“資料庫伺服器”下拉列表中選擇“建立新伺服器”,您將看到其他欄位。
步驟 5 − 輸入資料庫伺服器、使用者名稱和密碼。單擊“確定”。
步驟 6 − 專案建立後,執行應用程式,您將看到它正在 localhost 上執行。
步驟 7 − 要將這些應用程式部署到 Azure,請右鍵單擊解決方案資源管理器中的專案,然後選擇“釋出”。
您將看到以下對話方塊。
步驟 8 − 單擊“Microsoft Azure Web 應用”。
步驟 9 − 從現有 Web 應用中選擇您的應用程式名稱,然後單擊“確定”。
步驟 10 − 單擊“驗證連線”按鈕以檢查 Azure 上的連線。
步驟 11 − 單擊“下一步”繼續。
現在您將看到連線字串已預設生成。
步驟 12 − 單擊“下一步”繼續。
步驟 13 − 要檢查將釋出到 Azure 的所有檔案和 dll,請單擊“啟動預覽”。
步驟 14 − 單擊“釋出”按鈕以釋出您的應用程式。應用程式成功釋出到 Azure 後,您將在輸出視窗中看到訊息。
您還將看到該應用程式現在正在雲端執行。
讓我們再次轉到 Azure 門戶。您也可以在這裡看到該應用程式。
ASP.NET MVC - 自託管
在本章中,我們將介紹自託管。自託管為應用程式建立執行時環境,以便在任何環境(例如 MAC 或 Linux 系統)中執行。自託管還意味著它將具有迷你 CLR 版本。
使用檔案系統部署
讓我們來看一個簡單的自託管示例。
步驟 1 − 完成 ASP.NET MVC 應用程式後,如果要使用自託管,請右鍵單擊解決方案資源管理器中的專案。
您將看到以下對話方塊。
步驟 2 − 單擊“自定義”選項,這將顯示“新建自定義配置檔案”對話方塊。
步驟 3 − 輸入配置檔名稱,然後單擊“確定”。
步驟 4 − 從“釋出方法”下拉列表中選擇“檔案系統”,並指定目標位置。單擊“下一步”按鈕。
步驟 5 − 展開“檔案釋出選項”。
步驟 6 − 選中“釋出前刪除所有現有檔案”和“釋出期間預編譯”複選框,然後單擊“下一步”繼續。
步驟 7 − 單擊“釋出”按鈕,它將把檔案釋出到所需的位置。
您將在系統上的目標位置看到所有檔案和資料夾。
它將包含在本地主機上部署所需的所有檔案。
步驟 8 − 現在開啟“啟用或關閉 Windows 功能”,然後展開“Internet 資訊服務”→“全球資訊網服務”→“應用程式開發功能”。
步驟 9 − 選中如上圖所示的複選框,然後單擊“確定”。
步驟 10 − 讓我們開啟 IIS 管理器,如下面的螢幕截圖所示。
步驟 11 − 您將在螢幕左側看到不同的連線,右鍵單擊 MyWebSite。
步驟 12 − 選擇“轉換為應用程式”選項。
如您所見,其物理路徑與我們在使用檔案系統釋出時上面提到的相同。
步驟 13 − 單擊“確定”繼續。
現在您可以看到它的圖示已更改。
步驟 14 − 開啟您的瀏覽器並指定以下 URL https:///MyWebSite
您可以看到它正在我們部署期間指定的資料夾中執行。