ASP.NET MVC系列文章html
【01】淺談Google Chrome瀏覽器(理論篇)json
【02】淺談Google Chrome瀏覽器(操做篇)(上)瀏覽器
【03】淺談Google Chrome瀏覽器(操做篇)(下)緩存
【04】淺談ASP.NET框架 安全
【05】淺談ASP.NET MVC運行過程 網絡
【06】淺談ASP.NET MVC 控制器 mvc
【07】淺談ASP.NET MVC 路由 框架
【08】淺談ASP.NET MVC 視圖 ide
【09】淺談ASP.NET MVC 視圖與控制器傳遞數據post
【10】淺談jqGrid 在ASP.NET MVC中增刪改查
【13】淺談NuGet在VS中的運用
【14】淺談ASP.NET 程序發佈過程
1 概述
在閱讀本篇博文時,建議結合上篇博文:詳解ASP.NET MVC 路由 一塊兒閱讀,效果可能會更好些。
Controller(控制器)在ASP.NET MVC中負責控制全部客戶端與服務端的交互,而且負責協調Model與View之間數據傳遞,是ASP.NET MVC框架核心。Controller爲ASP.NET MVC框架的核心組成部分,其主要負責處理瀏覽器請求,並決定響應什麼內容給瀏覽器,但並不負責決定內容應如何顯示(View的職責)。
文章內容包括:Controller概述、Controller類別和方法、Controller運行過程、Controller方法類別、ViewData\ViewBag\TempData分析、ActionResult解說、Controller定義和參考文獻,剩下有關Controller其餘內容在本篇文章中不講,如Controller激活機制(Controller類型解析、Controller類型緩存、Controller的釋放和會話狀態行爲控制等)、ControllerFactory、ControllerBuilder等,除此以外,文中有些過於涉及到底層的內容,考慮篇幅等因素,只是簡要說起了一下,並未作深刻分析,根據後期狀況,會酌情考慮是否再寫一篇完全深刻的底層Controller的。
2 Controller類別和方法
Controller自己就是一個類(Class),該類別有許多方法(Method),這些方法中只要是公開方法(public method)就會被視爲是一個動做(Action)或動做方法(Action Method),只要動做存在,就能夠經過該動做方法接收客戶端傳來的要求與決定響應的檢視(View)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6
7 namespace MVCControllerDemo.Controllers 8 { 9 public class ControllerDemoController : Controller 10 { 11 //
12 // GET: /ControllerDemo/
13
14 [HttpGet] 15 public ActionResult Index() 16 { 17 return View(); 18 } 19 } 20 }
從如上代碼能夠總結出Controller應具有以下幾個基本條件:
(1)Controller必須爲公開類別;
(2)Controller名稱必須以Controller結尾;
(3)必須繼承自ASP.NET MVC內建的Controller類別,或實現IController自定義類別;
(4)因此動做方法必須爲公開方法,任何非公開的方法如聲明爲private或protected的方法都不會被視爲一個動做方法;
3 Controller的運行過程
當Controller被MvcHandler選中以後,下一步就是經過ActionInvoker選定適當的Action來運行。在Controllr中的每一個Action能夠定義0到多個參數,ActionInvoker會依據當下的RouteValue與客戶端傳來的數據準備好可傳入Action參數的數據,最後正式調用Controller中被選中的那個Action方法。參數傳入的屬性都是經過一種稱爲模型綁定(Model Binding)機制,從RequestContext取得數據,並將數據對應或傳入方法的參數中,讓Action不用再像以前ASP或ASP.NET Web Forms中常用的Request.Fomr或Request.QueryString等對象來取得客戶端的數據,經過自定義的模型綁定,甚至可讓你對應除了Request.Form或Request.QueryString之外的數據來源,例如:HTTP Cookies、HTTP Headers等等。
Action運行完後的回傳值一般是ActionResult類別或其衍生類別(Derived Class),事實上,ActionResult是一個抽象類,如ViewResult用來回傳一個View、RedirectResult用來將網頁重定向、Content回傳文字內容、FileResult回傳二進制文檔等,這些均是繼承ActionResult。MvcHandler從Controller獲得ActionResult以後,就會開始運行ActionResult提供的ExecuteResult方法,並將運行結果響應到客戶端,這時Controller的任務就算完成。
以上爲Controller的基本運行過程。Controller在運行時還有一層所謂的動做過濾器機制,分爲以下四種基本類型:
(1)受權過濾器(Authorization Filters);
(2)動做過濾器(Action Filters);
(3)結果過濾器(Result Filters);
(4)例外過濾器(Exception Fiters);
4 控制器方法類別
4.1 動做方法選定器
當經過ActionInvoker選定Controller內的公開方法時,ASP.NET MVC還有另外一個特性稱爲"動做方法選定器(Action Method Selector)",該選定器能夠套用在動做方法上,以便ActionInvoker"選定"適當的Action。
(1)NonAction屬性
若控制器某個方法特性爲NonAction,即便該Action方法是「公開方法」,也會告知ActionInvoker不要選定這個Action來運行。主要用途:a.保護Controller中的特定公開方法不要發佈到Web上;b.功能還沒有開發完成就要進行部署,暫時不想將此方法刪除。
1 [NonAction] 2 public ActionResult Index() 3 { 4 return View(); 5 }
也可將public改成private,達到保護的效果。
1 private ActionResult Index() 2 { 3 return View(); 4 }
(2)HTTP動詞限定屬性
HttpGet、HttpPost、HttpDelete、HttpPut、HttpHead、HttpOptions、HttpPatch屬性(Attributes)都是動做方法選定器的一部分。以下例子講解HttpGet屬性,即表明只有當客戶端瀏覽器發送HTTP GET要求時,ActionInvoker纔會選定到這個Action:
1 [HttpGet] 2 public ActionResult Index() 3 { 4 return View(); 5 }
若將[HttpGet]改成[HttpPost],瀏覽器將找不到資源。
1 [HttPost] 2 public ActionResult Index() 3 { 4 return View(); 5 }
註釋:若是動做方法上沒有嵌套任何限定屬性,那麼客戶端瀏覽器發送任意HTTP動詞都會自動選定到對應的Action。
當須要顯示接收窗體信息時,能夠建立兩個同名的Action,分別用[HttpGet](顯示窗體HTML)和[HttpPost](接收窗體輸出的值)屬性來限定。
1 [HttpGet] 2 public ActionResult Index() 3 { 4 return View(); 5 } 6
7 [HttpGet] 8 public ActionResult Create() 9 { 10 return View(); 11 } 12
13
14 [HttpPost] 15 public ActionResult Create(FormCollection fc) 16 { 17 //UpdateToDB(fc);
18 return RedirectToAction("Index"); 19 }
4.2 操做過濾器
一個操做方法一旦被選中就會當即執行,而且若是它返回一個結果,返回的結果也會隨後執行,ASP.NET MVC 5提供五種方式,分別列於以下:
除此以外,還有另一種過濾器,即重寫過濾器,它容許爲全局或控制器的默認集合制定例外狀況。
操做過濾器能夠做爲直接運用於操做方法或控制器類的特性來編寫,或做爲在全局過濾器列表中註冊的單獨類來編寫。若是打算將編寫的操做過濾器做爲特性來使用,那麼它必須繼承自FilterAttribute或它的任何子類,如ActionFilterAttribute。不做爲特性使用的全局操做過濾器沒有對這個基類的要求。不管採用哪一個路由,操做過濾器支持的過濾活動都由實現的接口決定。
5 Controller動做結果
5.1 控制器動做結果類型(ActionResult)
一般,在定義一個方法時,咱們常規性地根據方法是否有返回值歸結爲有返回值和無返回值兩大類,控制器的本質是類,控制器的action本質是方法,若是按照數學集合來定義,那麼控制器是類的一個子集,同理,控制器action是方法的一個子集,所以,在研究控制器以及控制器action時,咱們是能夠才用研究類和方法的通常思惟的。
控制器動做(具體的action)返回的結果叫作控制器動做結果,動做結果是控制器返回給瀏覽器請求的內容。ASP.NET MVC框架支持六種標準類型的動做結果。
(1)繼承ActionResult的動做結果
(2)繼承關係
(3)例子
eg1:ViewResult
1 //方法1: ViewResult做爲返回類型
2 public ViewResult Index() 3 { 4 return View(); 5 } 6
7
8
9 //方法二: ViewResultBase做爲返回類型
10 public ViewResultBase Index() 11 { 12 return View(); 13 } 14
15 //方法三: ActionResult做爲返回類型
16 public ActionResult Index() 17 { 18 return View(); 19 }
eg2:EmptyResult
1 // GET: /ControllerDemo/
2 public EmptyResult Index() 3 { 4 return null; 5 }
eg3:ContentResult
1 //方法1:ContentResult做爲返回類型
2 public ContentResult Index() 3 { 4 return Content("Hello World"); 5 } 6
7
8 //方法2:ActionResult做爲返回類型
9 public ActionResult Index() 10 { 11 return Content("Hello World"); 12 }
eg4:JsonResult
1 public JsonResult jsonResult() 2 2 { 3 3 TechInfoCompanay jsonCompany=new TechInfoCompanay(){id="S001",CompanyName="信息科技有限公司"}; 4 5 return Json(jsonCompany,JsonRequestBehavior.AllowGet); 5 6 } 6 7
7 8
8 9 //定義一個公司類
9 10 public class TechInfoCompanay 10 11 { 11 12 public string id { set; get; } 12 13 public string CompanyName { set; get; } 13 14 }
eg5:RedirectResult
1 //方法1:RedirectResult做返回類型
2 public RedirectResult redirectResult() 3 { 4 return Redirect("https://www.google.com.hk/");//具體的URL
5 } 6
7 //方法1: ActionResult做返回類型
8 public ActionResult redirectResult() 9 { 10 return Redirect("https://www.google.com.hk/");//具體的URL
11 }
eg6:RedirectToRouteResult
1 public ActionResult redirectResult() 2 { 3 return Redirect("https://www.google.com.hk/");//具體的URL
4 } 5
6 public RedirectToRouteResult redirectToRouteResult() 7 { 8 return RedirectToAction("Index"); 9 }
5.2通常方法
(1)以下只是給出方法樣式,不作具體代碼。
1 //無返回類型
2 public void functionName(形參) 3 { 4 //to add your content
5 } 6
7 //有返回類型
8 public 返回類型 functionName(形參) 9 { 10 //to add your content
11 return 與方法返回類型相匹配的結果; 12 }
(2)例子
eg:舉個自定義返回string的方法
RouteConfig.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7
8 namespace MVCControllerDemo 9 { 10 public class RouteConfig 11 { 12 public static void RegisterRoutes(RouteCollection routes) 13 { 14 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15
16 routes.MapRoute( 17 name: "Default", 18 url: "{controller}/{action}/{id}", 19 defaults: new { Controller = "ControllerDemo", action = "Index", id = UrlParameter.Optional } 20 ); 21 } 22 } 23 }
ControllerDemoController.action
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6
7 namespace MVCControllerDemo.Controllers 8 { 9 public class ControllerDemoController : Controller 10 { 11
12 public string GeneralFunction() 13 { 14 return "自定義通常方法"; 15 } 16 } 17 }
測試結果
6 ViewBag、ViewData和TempData概述
6.1 三者在MVC框架裏的定義
在MVC框架中,System.Web.Mvc命名空間下的ControllerBase中,對ViewBag、ViewData和TempData三個屬性的定義以下
ViewBag
1 [Dynamic] 2 public object ViewBag 3 { 4 [return: Dynamic] 5 get
6 { 7 Func<ViewDataDictionary> viewDataThunk = null; 8 if (this._dynamicViewDataDictionary == null) 9 { 10 if (viewDataThunk == null) 11 { 12 viewDataThunk = () => this.ViewData; 13 } 14 this._dynamicViewDataDictionary = new DynamicViewDataDictionary(viewDataThunk); 15 } 16 return this._dynamicViewDataDictionary; 17 } 18 }
ViewData
1 public ViewDataDictionary ViewData 2 { 3 get
4 { 5 if (this._viewDataDictionary == null) 6 { 7 this._viewDataDictionary = new ViewDataDictionary(); 8 } 9 return this._viewDataDictionary; 10 } 11 set
12 { 13 this._viewDataDictionary = value; 14 } 15 }
TempData
1 public TempDataDictionary TempData 2 { 3 get
4 { 5 if ((this.ControllerContext != null) && this.ControllerContext.IsChildAction) 6 { 7 return this.ControllerContext.ParentActionViewContext.TempData; 8 } 9 if (this._tempDataDictionary == null) 10 { 11 this._tempDataDictionary = new TempDataDictionary(); 12 } 13 return this._tempDataDictionary; 14 } 15 set
16 { 17 this._tempDataDictionary = value; 18 } 19 }
6.2 三者比較
(1)ViewData和TempData屬性均返回一個具備字典結構的數據容器,即字典類型的key/Value對,ViewBag爲Dynamic類型。
三者方法簽名爲:
1 public TempDataDictionary TempData { get; set; } 2 public ViewDataDictionary ViewData { get; set; } 3 public object ViewBag { [return: Dynamic] get; }
(2)TempData存儲臨時數據,而且設置的變量在被第一次讀取後會被移除,即TempData設置的變量只能被讀取一次。(why?)
(3)ViewBag和ViewData屬性是同一份數據的不一樣表現形式,兩者的不一樣之處在於前者是一個動態對象,能夠爲其指定任意屬性(動態屬性名將做爲數據字典的Key)。
(4)三者均是容器,即能存儲常量,變量,也能存儲集合。
7 ActionResult解說
在ASP.NET MVC框架中,對ActionResult定義以下:
1 // Generated by .NET Reflector from C:\Users\WJM\documents\visual studio 2013\Projects\DEMOMVC\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll 2 namespace System.Web.Mvc 3 { 4 using System; 5 6 public abstract class ActionResult 7 { 8 protected ActionResult() 9 { 10 } 11 12 public abstract void ExecuteResult(ControllerContext context); 13 } 14 }
ActionResult是Action運行後的回傳型別,可是當Action回傳ActionResult的時候,其實並不包含這個ActionResult(例如ViewResult)的運行結果,而是包含運行這個ActionResult時所需的數據,當MvcHandler從Controller取得ActionResult以後纔會去運行出ActionResult的結果。在ActionResult抽象類中僅僅定義了一個ExecuteResult()方法。
ASP.NET 定義瞭如下幾種衍生型別。
8 控制器定義
通常地,在定義Controller時,採用兩種方式,即實現IController和繼承Controller。
8.1 實現IController
RouteConfig.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7 8 namespace MVCControllerDemo 9 { 10 public class RouteConfig 11 { 12 public static void RegisterRoutes(RouteCollection routes) 13 { 14 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 16 routes.MapRoute( 17 name: "Default", 18 url: "{controller}/{action}/{id}", 19 defaults: new { Controller = "ControllerDemo", action = "Index", id = UrlParameter.Optional } 20 ); 21 } 22 } 23 }
RouteDemoController
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 7 using System.Reflection; 8 namespace MVCControllerDemo.Controllers 9 { 10 public class ControllerDemoController : IController 11 { 12 public String Index() 13 { 14 return "<h1>Index</h1>"; 15 } 16 17 18 19 public void Execute(System.Web.Routing.RequestContext requestContext) 20 { 21 string action = requestContext.RouteData.Values["action"].ToString(); 22 Type typ = typeof(ControllerDemoController); 23 MethodInfo md = typ.GetMethod(action, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 24 if (md == null) 25 { 26 requestContext.HttpContext.Response.Write("<h1>404</h1>"); 27 } 28 else 29 { 30 string s = md.Invoke(this, null).ToString(); 31 requestContext.HttpContext.Response.Write(s); 32 } 33 } 34 } 35 }
8.2 繼承Controller
這種方法比較經常使用。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 7 namespace MVCControllerDemo.Controllers 8 { 9 public class ControllerDemoController : Controller 10 { 11 // 12 // GET: /ControllerDemo/ 13 14 [HttpGet] 15 public ActionResult Index() 16 { 17 return View(); 18 } 19 } 20 }
9 參考文獻
【01】http://www.cnblogs.com/wangiqngpei557/p/3390812.html
【02】http://www.cnblogs.com/yaozhenfa/p/asp_net_mvc_controller.html
【03】http://www.360doc.com/content/12/0611/15/29831_217456312.shtml
【04】http://blog.csdn.net/yw1688/article/details/51280665
【05】Professional Asp.net MVC 5
【06】Professional Asp.net MVC 4
【07】The framework of revelation of Professional Asp.net MVC 5
【08】 https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/aspnet-mvc-controllers-overview-cs
10 版權