天天看點

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器

ASP.NET MVC系列文章

【01】淺談Google Chrome浏覽器(理論篇)

【02】淺談Google Chrome浏覽器(操作篇)(上)

【03】淺談Google Chrome浏覽器(操作篇)(下)

【04】淺談ASP.NET架構   

【05】淺談ASP.NET MVC運作過程    

【06】淺談ASP.NET MVC 控制器   

【07】淺談ASP.NET MVC 路由   

【08】淺談ASP.NET MVC 視圖 

【09】淺談ASP.NET MVC 視圖與控制器傳遞資料

【10】淺談jqGrid 在ASP.NET MVC中增删改查     

【11】淺談ASP.NET 頁面之間傳值的幾種方式

【12】淺談緩存技術在ASP.NET中的運用       

【13】淺談NuGet在VS中的運用      

【14】淺談ASP.NET 程式釋出過程           

【15】淺談資料注解和驗證           

【16】淺談依賴注入

【17】淺談表單和HTML輔助方法

【18】淺談基于APS.NET身份驗證

【19】淺談ASP.NET MVC 模型

【20】淺談ASP.NET MVC 單元測試

【21】淺談ASP.NET MVC網絡安全;

【22】淺談ASP.NET MVC八大類擴充

【23】再談ASP.NET MVC Routing

【24】淺談ASP.NET 進階話題

【25】淺談大型ASP.NET MVC項目(含DEMO)

【26】下一系列:ASP.NET WebAPI

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器

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 }      
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器

 注釋:如果動作方法上沒有嵌套任何限定屬性,那麼用戶端浏覽器發送任意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的動作結果

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器

(2)繼承關系

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器

 (3)例子

eg1:ViewResult

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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         }      

View Code

eg2:EmptyResult

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
1   // GET: /ControllerDemo/
2         public EmptyResult  Index()
3         {
4             return null;
5         }      

eg3:ContentResult

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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 }      

測試結果

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器

6  ViewBag、ViewData和TempData概述

6.1 三者在MVC架構裡的定義

在MVC架構中,System.Web.Mvc命名空間下的ControllerBase中,對ViewBag、ViewData和TempData三個屬性的定義如下

ViewBag

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
【ASP.NET MVC系列】淺談ASP.NET MVC 控制器
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 定義了以下幾種衍生型别。

【ASP.NET MVC系列】淺談ASP.NET MVC 控制器

8  控制器定義

一般地,在定義Controller時,采用兩種方式,即實作IController和繼承Controller。

8.1 實作IController

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  版權

  • 感謝您的閱讀,若有不足之處,歡迎指教,共同學習、共同進步。
  • 部落客網址:http://www.cnblogs.com/wangjiming/。
  • 極少部分文章利用讀書、參考、引用、抄襲、複制和粘貼等多種方式整合而成的,大部分為原創。
  • 如您喜歡,麻煩推薦一下;如您有新想法,歡迎提出,郵箱:[email protected]
  • 可以轉載該部落格,但必須著名部落格來源。

繼續閱讀