您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Asp.Net MVC中控制器與動作的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Asp.Net MVC中控制器與動作的示例分析”這篇文章吧。
一、理解控制器
1.1、什么是控制器
控制器是包含必要的處理請求的.NET類,控制器的角色封裝了應用程序邏輯,控制器主要是負責處理請求,實行對模型的操作,選擇視圖呈現給用戶。
簡單理解:實現了IController接口,修飾符必須是public,不能是抽象的,不能是泛型的,類名必須以Controller結尾。
在MVC框架中,控制器類必須實現System.Web.Mvc命名空間下的IController接口,如上圖所示,這是一個非常簡單的接口,該接口僅有一個Execute方法,當請求該控制器時Execute方法被調用。通過實現IController接口,你可以創建控制器類。
1.2、控制器的作用
a、每一個針對應用程序的請求,都是通過控制器自由地選擇合適的方式來處理的,只要它不偏離到視圖(View)和模型(Model)所負責的區域。
b、不要把業務或數據存儲的邏輯放到控制器里面,也不要創建用戶接口。
1.3、創建實現IController接口的控制器
示例: 創建一個實現Icontroller接口的類,讀取路由數據,并生成數據寫入響應。
在Controllers文件夾下創建一個名為MyFirstController的類,實現IController接口并添加如下代碼
運行該應用程序并在地址欄導航到/MyFirst,便可以看到此控制器產生的輸出。
創建一個類通過實現IController接口,MVC框架會將其視為一個控制器,并將請求發送給它,而且在如何處理和響應請求上沒有任何限制,這是一個很好的示例,因為它向你展示了MVC框架的可擴展性,但用這種方式編寫一個復雜的應用程序是非常困難的。
1.4、創建繼承于Controller類的控制器
通過System.Web.Mvc.Controller類你可以派生你的控制器,System.Web.Mvc.Controller類是大多數Web開發人員需要熟悉的,用來對請求處理提供支持的一個類,Controller提供了以下三個關鍵特性。
(1)、動作方法(Action Method):一個控制器的行為被分解成多個方法(而并非只有唯一的Execute()方法)。每個動作方法被暴露給不同的URL,并通過從輸入請求提取的參數進行調用。
(2)、動作結果(Action Result):你可以返回一個描述動作結果的對象(例如:渲染一個視圖,或重定向到一個不同的URL或動作方法),然后通過該對象實現你的目的。這種指定結果和執行之間的分離簡化了單元測試。
(3)、過濾器(Filter):你可以把可重用的行為封裝成過濾器,然后通過在代碼中添加特性的的方式,把這種行為標注到一個過多個控制器或動作方法上。
除非在頭腦中有一個非常明確的需求,否則創建控制器最好的辦法就是通過Controller類進行派生,這也正是你在Visual Studio中添加一個控制器,Visual Studio為你所做的事情。
在Controllers文件夾下創建一個名為MySecondController的類,繼承與Controller類,然后添加一個動作方法TestAction并編寫如下代碼返回一個動作結果,最后再該動作方法內右鍵添加對應的視圖。
運行應用程序并導航到/MySecond/TestAction瀏覽結果如下:
作為Controller類的一個派生類,所要做的工作是實現動作方法、獲取所需要的各種輸入,以對請求進行處理,并生成一個適當的響應。后面的內容將介紹數據的接收與響應。
二、控制器對數據的接收
2.1、數據來源
a、查詢字符串值 b、表單數據 c、路由數據
控制器需要經常訪問來自輸入請求的數據,如查詢字符串、表單數據、以及由路由系統根據輸入的URL解析得到的參數的值。訪問這些數據有三種主要方式。
(1)、從上下文對象提取。
(2)、作為參數被傳遞給動作方法(Action Method)而形成的數據。
(3)、明確調用框架的模型綁定(Model Binding)功能。
注意:參數名稱是忽略大小寫的,如Request["Test"]與Request["test"]結果是一樣的。如下圖:
View部分
Controller部分
2.2、通過上下文對象獲取數據
當創建一個從Controller基類派生的控制器時,就能夠訪問一組非常便利的屬性,這些屬性包括:Request、Response、RouteData、HttpContext、Server等,每一個屬性都包含了請求不同方面的的信息。在Action方法里是可以使用任何Context對象來訪問這些屬性。例如:
public ActionResult Index() { string userName = User.Identity.Name; string serverName = Server.MachineName; string clientIP = Request.UserHostAddress; DateTime dateStamp = HttpContext.Timestamp; string oldProductName = Request.Form["OldName"]; string newProductName = Request.Form["NewName"]; ViewBag.Message = "本機的IP是:" + clientIP; return View(); }
可以利用VS智能感知,在動作方法中輸入this.找到這些可用的上下文信息。
2.3、使用動作(Action)方法參數
2.3.1、使用Action方法參數
下面的方式是不是比上面的方法更優雅易讀呢?不過需要注意的是:Action方法里面是不允許有ref或out參數的,雖然編譯不會報錯但運行時會拋出一個異常。如下所示。
MySecond控制器代碼如下:
Index視圖代碼如下:
運行結果如下:
2.3.2、理解參數對象實例化
Controller基類使用叫做“值提供器(Value Provider)”和“模型綁定器(Model Binder)”的MVC框架組件來獲取動作方法的參數值。值提供器將可用的數據項集合呈現給控制器。有一組內建的值提供器從Request.For
m、Request.QueryString、Request.Files、RouteData.Values獲取數據項,然后這些值會被傳遞給模型綁定器,模型綁定器會嘗試將這些數據映射成動作方法參數的數據類型。默認的模型綁定能夠創建和填充任何.NET類型的對象,包括自定義的類型和集合。
2.3.3、理解可選參數與必須的參數
如果MVC框架找不到引用類型參數(如:string或object)的值,動作方法仍然會被調用,但對該參數會使用一個null值,若找不到值類型參數(如:int或double)的值則會拋出一個異常,并且不會調用動作方法。
a、值類型參數是必須被賦值的。如果想讓此參數和引用類型參數一樣,可以定義成int?如:public ActionResult Index(int? num),當依然沒有值時,不會發生異常,而是會傳遞null值。
b、引用類型的參數是可選的。為了使它成為必須的(保證一個非空的值被傳遞),在動作(Action)方法上添加一些代碼拒絕null。例如,在該值等于null時,拋出一個ArgumentNullException異常。
2.3.4、指定默認參數值
如果希望處理不含動作方法參數的請求,但又不想在代碼中檢查null值或拋出異常,可以使用C#的可選參數特性來代替。如下所示:
public ActionResult List(string query = "all", int page = 1) { //此處省略代碼N行... return View(); }
在定義參數時,通過對參數賦值的辦法,可以將參數標記為可選的,如上訴代碼中,給query和page參數提供了默認值。MVC框架會試圖通過請求為這些參數獲取值,但如果沒有值可用,那么將用所指定的默認值代替。
對于string類型參數query,注意string類型是引用類型,這意味著不需要檢查null值。如果請求為指定查詢字符串,那么該動作(Action)方法將以字符串“all”進行調用。對于int類型參數,注意int類型是值類型,在沒有page值時,請求不會導致錯誤,該方法將以默認值“1”進行調用。
三、控制器對數據的響應
3.1、理解動作結果(Action Result)
原理:
a、MVC框架接收從Action方法返回的ActionResult對象,并調用定義在ActionResult類里面ExecuteResult方法,對ActionResult進行實現,為我們處理Response對象并生成相關的輸出。
b、MVC框架內置了許多ActionResult類型,都是從ActionResult類派生的,能夠方便我們在Action方法里面選擇具體的返回類型,比如要呈現到View,可以選擇ViewResult作為Action方法的返回值。
MVC框架含有許多內置的動作結果類型如下圖所示,所有這些類型都是派生于ActionResult,其中在Controller類中有便利的輔助器方法。下面將解釋如何使用這些結果類型。
MVC框架支持的輸出類型有: 1.視圖 2.文本數據 3.XML數據 4.JSON數據 5.文件或者二進制數據 6.返回錯誤和HTTP Codes 7.定制的ActionResult 8.重定向
3.2、通過渲染視圖(View)返回HTML
最常見的來自Action方法的響應就是生成HTML并發送給瀏覽器,為了使用動作結果(ActionResult)生成HTML,需要創建一個指定了要呈現的視圖ViewResult類的實例。我們在Home控制器中編寫如下代碼.代碼中指定了HomePage的視圖。
當MVC框架調用ViewResult對象的ExecuteResult時,就會開始對指定的View進行搜素。
使用了區域(Area),則搜索順序如下:
1、/Area/<AreaName>/Views/<ControllerName>/<ViewName>.aspx
2、/Area/<AreaName>/Views/<ControllerName>/<ViewName>.ascx
3、/Area/<AreaName>/Views/Shared/<ControllerName>/<ViewName>.aspx
4、/Area/<AreaName>/Views/Shared/<ControllerName>/<ViewName>.ascx
5、/Area/<AreaName>/Views/<ControllerName>/<ViewName>.cshtml
6、/Area/<AreaName>/Views/<ControllerName>/<ViewName>.vbhtml
7、/Area/<AreaName>/Views/Shared/<ControllerName>/<ViewName>.chtml
8、/Area/<AreaName>/Views/Shared/<ControllerName>/<ViewName>.vbhtml
如果沒有使用區域(Area)或者在前面找不到則會在下面搜索,搜索順序如下:
1、/Views/<ControllerName>/<ViewName>.aspx
2、/Views/<ControllerName>/<ViewName>.ascx
3、/Views/Shared/<ControllerName>/<ViewName>.aspx
4、/Views/Shared/<ControllerName>/<ViewName>.ascx
5、/Views/<ControllerName>/<ViewName>.cshtml
6、/Views/<ControllerName>/<ViewName>.vbhtml
7、/Views/Shared/<ControllerName>/<ViewName>.chtml
8、/Views/Shared/<ControllerName>/<ViewName>.vbhtml
只要有一個視圖找到,就停止搜索,并開始將找到的視圖(View)呈現給客戶端。
通過路徑來指定呈現的視圖(View)
這種命名約定的方法非常方便和簡捷,但是它限制了我們所能呈現的一些視圖。如果要呈現一個具體的視圖,可以提供一個明確的路徑,下面是一個例子。
當我們這樣指定一個視圖時,指定的路徑必須以“/”或者“~/”并且包含擴展名(如:.aspx)。當然不推薦這樣來使用,因為這不利于程序的擴展和維護,這是一種綁定或耦合,有違MVC設計思想,可以有其他的方法來達到同樣的效果例如:使用RedirectToAction()方法。
View輔助方法
View():返回到Action同名的視圖。
View(“viewName”):返回到此控制器的ViewName視圖。
View(“~/views/othercontroller/viewname.cshtml”):這種方式必須以~/或者/開頭,但并不建議這么做,因為可以調用RedirectToAction這樣的方法。
View(“viewname”,”layout”):呈現這個視圖的時候,換一個母版頁。
3.3、將數據從動作(Action)方法傳遞給視圖(View)
傳輸數據的幾種方式:1.視圖模型 2.ViewData 3.ViewBag 4.TempData
3.3.1、提供視圖模型對象
將一個對象作為View方法的參數傳遞給視圖。例如:
Controller部分
public ViewResult Index2() { DateTime date = DateTime.Now; return View(date); }
View部分,添加視圖時,選擇Razor視圖引擎。
@{ ViewBag.Title = "Index2"; } <h3>Index</h3> The day is: @(((DateTime)Model).DayOfWeek)
上面的視圖是一個沒有類型或者說是弱類型的視圖,它不知道關于視圖模型對象的任何信息,并且將它作為object對象的實例進行處理。為了得到DayOfWeek屬性的值,需要將object對象的實例強轉為DateTime,這樣做能夠實現效果,但卻讓視圖變得雜亂。
我們可以通過創建強類型的View來改進,即在View里指定視圖模型對象的類型,只需要添加代碼:@model DateTime,如下所示:
@model DateTime @{ ViewBag.Title = "Index2"; } <h3>Index</h3> The day is: @Model.DayOfWeek
運行結果如下:
可以發現,使用強類型的視圖不僅讓視圖變得整潔,而且方便我們編碼,因為對屬性有智能感知。如下圖所示:
3.3.2、使用ViewBag傳遞數據
在前面我們已經使用過了ViewBag視圖包這個特性,該特性允許你在一個動態對象上定義任意屬性,并能夠在視圖里面訪問。如下所示:
Controller部分
public ViewResult Index2() { ViewBag.Message = "Hello ViewBag!"; ViewBag.Date=DateTime.Now; return View(); }
View 部分
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index2</title> </head> <body> <div> the message is:@ViewBag.message<br/> the day is:@ViewBag.Date.DayOfWeek </div> </body> </html>
運行效果如下:
相對于視圖模型對象方面,ViewBag有一個優點,即它能夠很容易地發送多個對象到視圖。假如我們被限制只能使用視圖模型,那么為了實現相同的效果需要創建一個新的類型具有string和DateTime兩個類型的的成員。使用動態對象可以在視圖中輸入屬性和方法調用的任意序列。
3.3.3、使用ViewData傳遞數據
ViewData是在MVC3之前的版本中出現的,主要的功能類似于ViewBag,但ViewData是使用ViewDataDictionary類實現的而不是一個動態的類型,ViewDataDictionary類是一個常規的鍵/值對的集合,并通過Controller類的ViewData屬性訪問。如下示例:
Controller部分
public ViewResult Index2() { ViewData["message"] = "Hello ViewBag!"; ViewData["Date"]=DateTime.Now; return View(); }
View部分
public class MySecondController : Controller { public ActionResult Index() { TempData["Message"] = "Hello TempData"; TempData["Data"] = "TempData的值只能讀取一次"; return View(); } public ActionResult TempDataTest() { return View(); } }
運行結果與VIewBag運行結果一致。
上面的代碼中,我們看到ViewData需要對object對象進行類型轉換,現在有了ViewBag以后,推薦使用ViewBag,并且盡量使用強類型視圖和視圖模型。
3.3.4、使用TempData傳遞數據
在【3.4.4、使用TempData保留重定向數據】節中會介紹使用TempData傳遞數據,這里不作介紹。
3.4、執行重定向
有一種動作(Action)方法的通常結果并不是直接產生輸出,而是把用戶的瀏覽器重定向導另一個URL。大多數情況下,這個URL是應用程序的另一個動作(Action)方法,用來生成你希望用戶看到的輸出。
重定向的Action方法不產生任何的輸出,只是讓瀏覽器重新請求一個其它的URL。在MVC程序中,一般會定向到其它的Action方法來產生輸出。
在執行重定向時,發送了兩個HTTP代碼中的一個到瀏覽器。
(1)、發送HTTP 302狀態編碼,代表暫時重定向。(常用類型)
(2)、發送HTTP 301狀態編碼,表示永久重定向。(使用需謹慎)
重定向的類型有:1.重定向到文本URL 2.重定向到路由系統的URL 3.重定向到動作(Action)方法
3.4.1、重定向到文本URL
對瀏覽器重定向最基本的方式是調用Redirect方法,它返回RedirectResult類的一個實例。如下示例:
如果希望重定的URL被表示成一個字符串,并作為參數傳遞給Redirect方法。Redirect方法發送的是一個臨時重定向。可以用RedirectPermanent方法發送一個永久重定向。例如:
3.4.2、重定向到路由系統的URL
使用重定向到文本URL的缺點是:限定了URL,當路由發生改變后,必須更新URL。幸好我們可以使用路由系統,用RedirectToRoute方法來生成有效的URL該方法會創建 RedirectToRouteResult的一個實例。如下所示:
3.4.3、重定向到動作(Action)方法
使用RedirectToAction方法能夠很優雅的重定向到一個Action方法,這個方法僅僅是對RedirectToRoute方法的封裝,讓你指定Action方法和控制器的值,而不需要創建一個匿名類型。如下所示:
如果想重定向到其他的控制器,需要提供一個控制器的名稱如:
注意:傳入的Action參數或控制器參數在它們被傳遞給路由系統之前是不會被驗證的,所以要確保目標控制器和Action方法是存在的。
3.4.4、使用TempData保留重定向數據
重定向會引起瀏覽器提交整個新的HTTP請求,這意味著無法訪問原始的請求的細節。如果想將數據從一個請求傳遞到下一個請求,可以使用TempData()方法。
TempData類似于Session,不同的是TempData在被讀取以后會被標記刪除,并且當請求被處理的時候被移除。這是一個針對想在整個重定向過程中保持短期數據的非常完美的安排。如下示例:
首先添加一個MySecond控制器,并添加對應的視圖,視圖引擎為Razor并編寫如下代碼:
MySecond控制器代碼
public class MySecondController : Controller { public ActionResult Index() { TempData["Message"] = "Hello TempData"; TempData["Data"] = "TempData的值只能讀取一次"; return View(); } public ActionResult TempDataTest() { return View(); } }
Index視圖代碼
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> the Data is:@TempData["Data"] </div> </body> </html>
TempDataTest視圖代碼
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>TempDataTest</title> </head> <body> <div> the Data is:@TempData["Data"]<br/> the Message is:@TempData["Message"] </div> </body> </html>
運行結果如下:
注意:在Index里面沒有讀取TempData["Message"]的值,但是Index和TempDataTest都讀取了TempData["Data"]的值。這樣做是為了驗證TempData里面的值在不同的視圖只能讀取一次。
TempData里面的值在一次請求里面只能讀取一次。 如果我們想讀取TempData的值但是又不讓它被刪除,可以使用TempData.Peek(“Data”)方法。 如果想在保持一次TempData里面的值,可以使用TempData.Keep("Data")。
3.5、返回文本數據
Content方法參數說明: 發送的文本數據、響應的HTTP content-type header、編碼格式。 可以忽略最后兩個參數,在MVC框架假定數據是HTML(content type為text/html)情況下,它會查詢一種瀏覽器聲明支持的編碼格式。
3.6、返回XML數據
using LinqService; using System.Xml.Linq; public ContentResult GetXMLData() { List<Books> books = bll.GetListBooks(); XElement data = new XElement("BooksList", books.Select(e => { return new XElement("Books", new XAttribute("title", e.Title), new XAttribute("author", e.Author), new XAttribute("Price", e.Price.ToString())); })); }
3.7、返回JSON數據
public ActionResult JSON() { JsonResult json = new JsonResult(); UserInfo userinfo=new UserInfo{ ID=1, Name="張三", Age=11 }; List<UserInfo> list=new List<UserInfo>{ new UserInfo{ ID=1, Name="張三", Age=11 }, new UserInfo{ ID=1, Name="張三", Age=11 }, new UserInfo{ ID=1, Name="張三", Age=11 }, new UserInfo{ ID=1, Name="張三", Age=11 } }; //json.Data = list; //json.JsonRequestBehavior = JsonRequestBehavior.AllowGet; //return json; //return new JsonResult() { Data = list, JsonRequestBehavior=JsonRequestBehavior.AllowGet }; return Json(userinfo,JsonRequestBehavior.AllowGet); }
JSON是一個輕量級的基于文本格式,用來描述分層數據結構的, JSON是有效的javascript代碼,這意味著被所有的主流瀏覽器支持
在MVC框架里面內置了JsonResult類,讓我們能夠序列化.NET對象為json格式。通過Json方法可以創建返回JsonResult結果類型
3.8、返回文件和二進制數據
public FileResult AnnualReport() { string filename = @"D:\C#高級編程.doc"; string contentType = "application/doc"; string downloadName = "C#高級編程2013.doc"; return File(filename, contentType, downloadName); }
如果不知道具體的MIME類型,可以指定contentType 為application/octet-stream
lFileResult是一個抽象基類,其三個實現的子類 :
1.FilePathResult :直接把服務器的某個路徑下的文件發給瀏覽器
2.FileContentResult :發送一個內存中的二進制數據給瀏覽器
3.FileStreamResult:發送已經打開的文件流內容給瀏覽器。
3.9、返回錯誤和HTTP Codes
發送特定的HTTP結果碼
可以使用HttpStatusResult類將一個特定的HTTP狀態碼發送給瀏覽器。這個類沒有對應的控制器輔助器方法,因此必須直接對這個類進行實例化,如下所示:
public HttpStatusCodeResult StatusCode() { return new HttpStatusCodeResult(404,"file not found"); }
發送404結果
可以使用便利的HttpNotFoundResult類來獲取上面相同的效果,這個類派生于HttpStatusResult,而且可以用控制器的便利方法HttpNotFound來創建。如下所示:
public HttpStatusCodeResult StatusCode() { return HttpNotFound(); }
發送401結果
另一個特定的HTTP狀態碼的封裝程序類是HttpUnauthorizeResult,它返回401代碼,用來指示一個未授權請求。如下所示:
public HttpStatusCodeResult StatusCode() { return new HttpUnauthorizedResult(); }
總結:在本文章中,主要是對MVC設計模式中的控制器和動作方法做了詳細介紹,主要從實現自定義的控制器類兩種方式著手,然后介紹了控制器對數據的接收與響應系列內容。對數據接收主要來源查詢字符串值、表單數據、路由數據做了分別介紹,對數據的響應包括視圖 、文本數據、XML數據、JSON數據、文件或者二進制數據、返回錯誤和HTTP Codes、定制的ActionResult、重定向做了分別介紹。
以上是“Asp.Net MVC中控制器與動作的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。