精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

詳解ASP.NET MVC Controller激活系統:總體設計

開發 后端
本文將給大家談談ASP.NET MVC Controller激活系統。包括Controller激活系統在ASP.NET MVC中的總體設計,了解一下組成該子系統的一些基本的組件,以及它們對應的接口或者抽象類是什么。

我們將整個ASP.NET MVC框架劃分為若干個子系統,那么針對請求上下文激活目標Controller對象的子系統被我們成為Controller激活系統。在正式討論Controller對象具體是如何被創建愛之前,我們先來看看Controller激活系統在ASP.NET MVC中的總體設計,了解一下組成該子系統的一些基本的組件,以及它們對應的接口或者抽象類是什么。

目錄

一、Controller
二、 ControllerFactory
三、ControllerBuilder
實例演示:如何提升命名空間的優先級
針對Area的路由對象的命名空間
四、 Controller的激活與URL路由

一、Controller

我們知道作為Controller的類型直接或者間接實現了IController接口。如下面的代碼片斷所示,IController接口僅僅包含一個參數類型為RequestContext的Execute方法。當一個Controller對象被激活之后,核心的操作就是根據請求上下文解析出目標Action方法,并通過Model綁定機制從請求上下文中提取相應的數據映射為方法的參數并最終執行Action方法。所有的這些操作都是調用這個Execute方法來執行的。

  1. public interface IController  
  2. {  
  3.     void Execute(RequestContext requestContext);  

定義在IController接口中的Execute是以同步的方式執行的。為了支持以異步方式對請求的處理,IController接口的異步版本System.Web.Mvc.IAsyncController被定義出來。如下面的代碼片斷所示,實現了IAsyncController接口的異步Controller的執行通過BeginExecute/EndExecute方法組合來完成。

  1. public interface IAsyncController : IController  
  2.    {  
  3.        IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state);  
  4.       void EndExecute(IAsyncResult asyncResult);  
  5.     } 

抽象類ControllerBase實現了IController接口,它具有如下幾個重要的屬性。TemplateData、ViewBag和ViewData用于存儲從Controller向View傳遞的數據或者變量。其中TemplateData和ViewData具有基于字典的數據結構,Key和Value分別表示變量的名稱和值,所不同的前者用于存儲基于當前HTTP上下文的變量(在完成當前請求后,存儲的數據會被回收)。ViewBag和ViewData具有相同的作用,甚至對應著相同的數據存儲,它們之間的不同之處在于前者是一個動態對象,我們可以為其指定任意屬性。

  1. public abstract class ControllerBase : IController  
  2. {     
  3.     //其他成員  
  4.    public ControllerContext ControllerContext { getset; }  
  5.     public TempDataDictionary TempData { getset; }  
  6.     public object ViewBag { [return: Dynamic] get; }  
  7.    public ViewDataDictionary ViewData { getset; }  

在ASP.NET MVC中我們會陸續遇到一系列的上下文(Context)對象,之前我們已經對表示請求上下文的RequestContext(HttpContext + RouteData)進行了詳細的介紹,現在我們來介紹另一個具有如下定義的上下文類型ControllerContext

  1. public class ControllerContext  
  2.  {  
  3.      //其他成員  
  4.      public ControllerContext();  
  5.      public ControllerContext(RequestContext requestContext, ControllerBase controller);  
  6.     public ControllerContext(HttpContextBase httpContext,   
  7.      RouteData routeData, ControllerBase controller);  
  8.      public virtual ControllerBase Controller { getset; }  
  9.    public RequestContext RequestContext { getset; }  
  10.     public virtual HttpContextBase HttpContext { getset; }  
  11.     public virtual RouteData RouteData { getset; }  

顧名思義,ControllerContext就是基于某個Controller對象的上下文。從如下的代碼所示,ControllerContext是實際上是對一個Controller對象和RequestContext的封裝,這兩個對象分別對應著定義在ControllerContext中的同名屬性,并且可以在構造函數中被初始化。而通過屬性HttpContext和RouteData屬性返回的HttpContextBase和RouteData對象在默認情況下實際上就是組成RequestContext的核心元素。ControllerContext的這四個屬性都是可讀可寫的,我們對其進行任意地修改。當ControllerBase的Execute方法被執行的時候,它會根據傳入的ReuqestContext創建ControllerContext對象,而后續的操作可以看成是在該上下文中進行。

當我們在進行開發的時候,通過VS默認創建的Controller類型實際上繼承自抽象類Controller。該類型中定義了很多的輔助方法和屬性以編程變得簡單。如下面的代碼片斷所示,除了直接繼承ControllerBase之外,Controller類型還顯式實現了IController和IAsyncController接口,以及代表ASP.NET MVC 四大篩選器(AuthorizationFilter、ActionFilter、ResultFilter和ExceptionFilter)的4個接口。

  1. public abstract class Controller :   
  2.      ControllerBase,        
  3.      IController,   
  4.     IAsyncController,  
  5.      IActionFilter,   
  6.      IAuthorizationFilter,   
  7.      IExceptionFilter,   
  8.     IResultFilter,    
  9.      IDisposable,   
  10.    ...  
  11. {  
  12.    //省略成員  

二、 ControllerFactory

ASP.NET MVC為Controller的激活定義相應的相應的工廠,我們將其統稱為ControllerFactory,所有的ControllerFactory實現了接口IControllerFactory接口。如下面的代碼片斷所示,Controller對象的激活最終最終通過IControllerFactory的CreateController方法來完成,該方法的兩個參數分別表示當前請求上下文和從路由信息中獲取的Controller的名稱(最初來源于請求地址)。

  1. public interface IControllerFactory  
  2.  {  
  3.     IController CreateController(RequestContext requestContext, string controllerName);  
  4.     SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);  
  5.     void ReleaseController(IController controller);  
  6.  }  
  7. public enum SessionStateBehavior  
  8.  
  9.      Default,  
  10.    Required,  
  11.    ReadOnly,  
  12.    Disabled  

處理負責創建Controller處理請求之前,ControllerFactory還需要在完成請求處理之后實施對Controller的釋放回收,后者實現在ReleaseController方法中。IControllerFactory的另一個方法GetControllerSessionBehavior方法返回一個SessionStateBehavior枚舉。熟悉ASP.NET的讀者應該對SessionStateBehavior不會感到陌生,它用于表示請求處理過程中會話狀態支持的模式,它的四個枚舉值分別具有如下的含義:

  • Default:使用默認 ASP.NET 邏輯來確定請求的會話狀態行為。
  • Required:為請求啟用完全的讀寫會話狀態行為。
  • ReadOnly:為請求啟用只讀會話狀態。
  • Disabled:禁用會話狀態。

對于Default選項來說,ASP.NET通過映射的HttpHandler類型是否實現了相關接口來決定具體的會話狀態控制行為。在System.Web.SessionState命名空間下定義了IRequiresSessionState和IRequiresSessionState接口,如下面的代碼片斷所示,這兩個都是不具有任何成員的空接口(我們一般稱之為標記接口),而IReadOnlySessionState繼承自IRequiresSessionState。如果HttpHandler實現了接口IReadOnlySessionState,則意味著采用ReadOnly模式,如果只實現了IRequiresSessionState則采用Required模式。

   1: public interface IRequiresSessionState
   2: {}
   3: public interface IReadOnlySessionState : IRequiresSessionState
   4: {}

具體采用何種會話狀態行為取決于當前HTTP上下文(HttpContext.Current)。對于之前的版本,我們不能對當前HTTP上下文的會話狀態行為模式進行動態的修改,ASP.NET 4.0為HttpContext定義了如下一個SetSessionStateBehavior方法是我們可以自由地選擇會話狀態行為模式。相同的方法同樣定義在HttpContextBase中,它的子類HttpContextWrapper重寫了這個方法并在內部會調用封裝的HttpContext的同名方法。

  1. public sealed class HttpContext : IServiceProvider, IPrincipalContainer  
  2.  {  
  3.     //其他成員  
  4.  public void SetSessionStateBehavior(  
  5.      SessionStateBehavior sessionStateBehavior);  
  6.  }  
  7.  public class HttpContextBase: IServiceProvider  
  8.  {  
  9.     //其他成員  
  10.     public void SetSessionStateBehavior(SessionStateBehavior sessionStateBehavior);  

三、ControllerBuilder

用于激活Controller對象的ControllerFactory最終通過ControllerBuilder注冊到ASP.NET MVC應用中。如下面的代碼所示,ControllerBuilder定義了一個靜態只讀屬性Current返回當前ControllerBuilder對象,這是針對整個Web應用的全局對象。兩個SetControllerFactory方法重載用于注冊ControllerFactory的類型或者實例,而GetControllerFactory方法返回一個具體的ControllerFactory對象。

  1. public class ControllerBuilder  
  2.  
  3.     public IControllerFactory GetControllerFactory();  
  4.    public void SetControllerFactory(Type controllerFactoryType);  
  5.     public void SetControllerFactory(IControllerFactory controllerFactory);    
  6.     public HashSet<string> DefaultNamespaces { get; }  
  7.    public static ControllerBuilder Current { get; }  

具體來說,如果我們是注冊的ControllerFactory的類型,那么GetControllerFactory在執行的時候會通過對注冊類型的反射(調用Activator的靜態方法CreateInstance)來創建具體的ControllerFactory(系統不會對創建的Controller進行緩存);如果注冊的是一個具體的ControllerFactory對象,該對象直接從GetControllerFactory返回。

被ASP.NET路由系統進行攔截處理后會生成一個用于封裝路由信息的RouteData對象,而目標Controller的名稱就包含在通過該RouteData的Values屬性表示的RouteValueDisctionary對象中,對應的Key為“controller”。而在默認的情況下,這個作為路由數據的名稱只能幫助我們解析出Controller的類型名稱,如果我們在不同的命名空間下定義了多個同名的Controller類,會導致激活系統無法確定具體的Controller的類型從而拋出異常。

為了解決這個問題,我們必須為定義了同名Controller類型的命名空間設置不同的優先級,具體來說我們有兩種提升命名空間優先級的方式。***種方式就是在調用RouteCollection的擴展方法MapRoute時指定一個命名空間的列表。通過這種方式指定的命名空間列表會保存在Route對象的DataTokens屬性表示的RouteValueDictionary字典中,對應的Key為“Namespaces”。

  1. public static class RouteCollectionExtensions  
  2.  {  
  3.      //其他成員        
  4.      public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);      
  5.      public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);      
  6.      public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);  
  7.  }  

而另一種提升命名空間優先級的方式就是將其添加到當前的ControllerBuilder中的默認命名空間列表中。從上面的給出的ControllerBuilder的定義可以看出,它具有一個HashSet<string>類型的只讀屬性DefaultNamespaces就代表了這么一個默認命名空間列表。對于這兩種不同的命名空間優先級提升方式,前者(通過路由注冊)指定命名空間具有更高的優先級。

實例演示:如何提升命名空間的優先級

為了讓讀者對此如何提升命名空間優先級具有一個深刻的印象,我們來進行一個簡單的實例演示。我們使用Visual Studio提供的項目模板創建一個空的ASP.NET MVC應用,并且使用如下所示的默認路由注冊代碼。

  1.  public class MvcApplication : System.Web.HttpApplication  
  2.  {  
  3.      public static void RegisterRoutes(RouteCollection routes)  
  4.      {        
  5.          routes.MapRoute(  
  6.              name: "Default",  
  7.              url: "{controller}/{action}/{id}",  
  8.              defaults: new { controller = "Home", action = "Index",   
  9.                  id = UrlParameter.Optional }  
  10.         );  
  11.    }  
  12.     protected void Application_Start()  
  13.     {  
  14.         //其他操作  
  15.         RegisterRoutes(RouteTable.Routes);  
  16.     }  
  17. }  
  18. public class MvcApplication : System.Web.HttpApplication  
  19. {  
  20.     public static void RegisterRoutes(RouteCollection routes)  
  21.     {        
  22.         routes.MapRoute(  
  23.             name: "Default",  
  24.             url: "{controller}/{action}/{id}",  
  25.             defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }  
  26.         );  
  27.     }  
  28.     protected void Application_Start()  
  29.     {  
  30.         //其他操作  
  31.         RegisterRoutes(RouteTable.Routes);  
  32.     }  

然后我們在Controllers目錄下添加一個.cs 文件,并在該文件中定義兩個同名的Controller類。如下面的代碼片斷所示,這兩個HomeCotroller類分別定義在命名空間Artech.MvcAppArtech.MvcApp.Controllers之中,而Index操作返回的是一個將Controller類型全名為內容的ContentResult對象。

  1.  namespace Artech.MvcApp.Controllers  
  2.  {  
  3.      public class HomeController : Controller  
  4.      {  
  5.          public ActionResult Index()  
  6.          {  
  7.              return this.Content(this.GetType().FullName);  
  8.          }  
  9.      }  
  10.  
  11. namespace Artech.MvcApp  
  12. {  
  13.     public class HomeController : Controller  
  14.    {  
  15.         public ActionResult Index()  
  16.        {  
  17.            return this.Content(this.GetType().FullName);  
  18.        }  
  19.    }  

現在我們直接運行該Web應用。由于具有多個Controller與注冊的路由規則相匹配導致ASP.NET MVC的Controller激活系統無法確定目標哪個類型的Controller應該被選用,所以會出現如下圖所示的錯誤。

image

目前定義了HomeController的兩個命名空間具有相同的優先級,現在我們將其中一個定義在當前ControllerBuilder的默認命名空間列表中以提升匹配優先級。如下面的代碼片斷所示,在Global.asax 的Application_Start方法中,我們將命名空間“Artech.MvcApp.Controllers”添加到當前ControllerBuilder的DefaultNamespaces屬性所示的命名空間列表中

   1: public class MvcApplication : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start()
   4:     {
   5:         //其他操作            
   6:         ControllerBuilder.Current.DefaultNamespaces.Add("Artech.MvcApp.Controllers");
   7:     }
   8: }

對用同時匹配注冊的路由規則的兩個HomeController,由于“Artech.MvcApp.Controllers”命名空間具有更高的匹配優先級,所有定義其中的HomeController會被選用,這可以通過如下圖所示的運行結果看出來。

image

為了檢驗在路由注冊時指定的命名空間和作為當前ControllerBuilder的命名空間哪個具有更高匹配優先級,我們修改定義在Global.asax中的路由注冊代碼。如下面的代碼片斷所示,我們在調用RouteTable的靜態屬性Routes的MapRoute方法進行路由注冊的時候指定了命名空間(“Artech.MvcApp”)

  1. public class MvcApplication : System.Web.HttpApplication  
  2. {  
  3.     public static void RegisterRoutes(RouteCollection routes)  
  4.     {        
  5.         routes.MapRoute(  
  6.             name: "Default",  
  7.             url: "{controller}/{action}/{id}",  
  8.             defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },  
  9.             namespaces:new string[]{"Artech.MvcApp"}  
  10.        );  
  11.    }  
  12.     protected void Application_Start()  
  13.   {  
  14.       //其他操作  
  15.       RegisterRoutes(RouteTable.Routes);   
  16.      ControllerBuilder.Current.DefaultNamespaces.Add("Artech.MvcApp.Controllers");  
  17.    }  

再次運行我們的程序會在瀏覽器中得到如圖3-3所示的結果,從中可以看出定義在命名空間“Artech.MvcApp”中的HomeController被最終選用,可見較之作為當前ControllerBuilder的默認命名空間,在路由注冊過程中執行的命名空間具有更高的匹配優先級,前者可以視為后者的一種后備。

image

在路由注冊時指定的命名空間比當前ControllerBuilder的默認命名空間具有更高的匹配優先級,但是對于這兩個集合中的所有命名空間卻具有相同的匹配優先級。換句話說,用于輔助解析Controller類新的命名空間分為三個梯隊,簡稱為路由命名空間、ConrollerBuilder命名空間和Controller類型命名空間,如果前一個梯隊不能正確解析出目標Controller的類型,則將后一個梯隊的命名空間作為后備;反之,如果根據某個梯隊的命名空間進行解析得到多個匹配的Controller類型,會直接拋出異常

現在我們對本例的路由注冊代碼作了如下的修改,為注冊的路由對象指定了兩個命名空間(分別是兩個HomeContrller所在的命名空間),運行我們的程序依然會得到如***張圖所示的錯誤。

  1.  public class MvcApplication : System.Web.HttpApplication  
  2.  {  
  3.      public static void RegisterRoutes(RouteCollection routes)  
  4.      {        
  5.          routes.MapRoute(  
  6.              name: "Default",  
  7.              url: "{controller}/{action}/{id}",  
  8.              defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },  
  9.              namespaces: new string[] { "Artech.MvcApp""Artech.MvcApp.Controllers" }  
  10.         );  
  11.     }  
  12.     protected void Application_Start()  
  13.   {  
  14.         //其他操作  
  15.      RegisterRoutes(RouteTable.Routes);  
  16.    }  

針對Area的路由對象的命名空間

針對某個Area的路由映射是通過相應的AreaRegistration進行注冊的,具體來說是在AreaRegistration的RegisterArea方法中調用AreaRegistrationContext對象的MapRoute方法進行注冊的。如果在調用MapRoute方法中指定了表示命名空間的字符串,將自動作為注冊的路由對象的命名空間,否則會將表示AreaRegistration所在命名空間的字符串加上“.*”后綴作為路由對象的命名空間。這里所說的“路由對象的命名空間”指的就是通過Route對象的DataTokens屬性表示的RouteValueDictionary對象中Key為“Namespaces”的字符串數組,而該字符串最終會轉移到生成的RouteData的DataTokens中。

除此之外,在調用AreaRegistrationContext的MapRoute方法時還會在注冊Route對象DataTokens中添加一個Key為“UseNamespaceFallback”的條目表示是否采用后備命名空間對Controller類型進行解析。如果注冊對象具有命名空間(調用MapRoute方法時指定了命名空間或者對應的AreaRegistration類型定義在某個命名空間中),該條目的值為False;否則為True。該條目同樣反映在通過該Route對象生成的RouteData對象的DataTokens屬性中。[關于ASP.NET MVC路由,在我的文章《ASP.NET MVC路由擴展:路由映射》中具有詳細的介紹]

在解析Controller真實類型的過程中,會先通過RouteData包含的命名空間來解析Controller類型。如果Controller類型解析失敗,則通過包含在通過RouteData的DataTokens屬性表示的RouteValueDictionary對象中的這個UseNamespaceFallback值來判斷是否使用“后備”命名空間進行解析。具體來說,如果該值為True或者不存在,則先通過當前ControllerBuilder的命名空間解析,如果失敗則忽略命名空間直接采用類型名稱進行匹配;否則直接因找不到匹配的Controller而拋出異常

我們通過具體的例子來說明這個問題。在一個通過Visual Studio的ASP.NET MVC項目創建的空Web應用中,我們添加一個名稱為Admin的Area,此時IDE會默認為我們添加如下一個AdminAreaRegistration類型。

   1: namespace Artech.MvcApp.Areas.Admin
   2: {
   3:     public class AdminAreaRegistration : AreaRegistration
   4:     {
   5:         public override string AreaName
   6:         {
   7:             get{return "Admin";}
   8:         }
   9:         public override void RegisterArea(AreaRegistrationContext context)
  10:         {
  11:             context.MapRoute("Admin_default", "Admin/{controller}/{action}/{id}",
  12:                 new { action = "Index", id = UrlParameter.Optional }
  13:             );
  14:         }
  15:     }
  16: }

AdminAreaRegistration類型定義在命名空間Artech.MvcApp.Areas.Admin中。現在我們在該Area中添加一個Controller類,其名為HomeController。默認情況下,我們添加的Controller類型和AdminAreaRegistration具有相同的命名空間,但是現在我們刻意將命名空間改為Artech.MvcApp.Areas

  1. namespace Artech.MvcApp.Areas  
  2. {  
  3.     public class HomeController : Controller  
  4.     {  
  5.         public ActionResult Index()  
  6.         {  
  7.             return Content("...");  
  8.         }  
  9.     }  

現在我們在瀏覽器中通過匹配的URL(/Admin/Home/Index)來訪問Area為Admin的HomeController的Index操作,會得到如下圖所示的HTTP狀態為404的錯誤。這就是因為在對Controller類型進行解析的時候是嚴格按照對應的AreaRegistration所在命名空間來進行的,很顯然在這個范圍內是不可能找得到對應的Controller類型的。

image

四、Controller的激活與URL路由

ASP.NET路由系統是HTTP請求抵達服務端的***道屏障,它根據注冊的路由規則對攔截的請求進行匹配并解析包含目標Controller和Action名稱的路由信息。而當前ControllerBuilder具有用于激活Controller對象的ControllerFactory,我們現在看看兩者是如何結合起來的。

通過《ASP.NET路由系統實現原理:HttpHandler的動態映射》介紹我們知道ASP.NET路由系統的核心是一個叫做UrlRoutingModule的自定義HttpModule,路由的實現是它通過注冊代表當前Web應用的HttpApplication的PostResolveRequestCache事件對HttpHandler的動態映射來實現的。具體來說,它通過以RouteTable的靜態屬性Routes代表的全局路由表對請求進行匹配并得到一個RouteData對象。RouteData具有一個實現了接口IRouteHandler的屬性RouteHandler,通過該屬性的GetHttpHandler方法得到最終被映射到當前請求的HttpHandler

對于ASP.NET MVC應用來說,RouteData的RouteHandler屬性類型為MvcRouteHandler,體現在MvcRouteHandler類型上關于HttpHandler的提供機制基本上(不是完全等同)可以通過如下的代碼來表示。MvcRouteHandler維護著一個ControllerFactory對象,該對象可以在構造函數中指定,如果沒有顯示指定則直接通過調用當前ControllerBuilder的GetControllerFactory方法獲取。

  1.  public class MvcRouteHandler : IRouteHandler  
  2.  {  
  3.      private IControllerFactory _controllerFactory;  
  4.       public MvcRouteHandler(): this(ControllerBuilder.Current.GetControllerFactory())  
  5.      { }  
  6.      public MvcRouteHandler(IControllerFactory controllerFactory)  
  7.     {  
  8.         _controllerFactory = controllerFactory;  
  9.     }  
  10.     IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)  
  11.    {  
  12.        string controllerName = (string)requestContext.RouteData.GetRequiredString("controller");  
  13.        SessionStateBehavior sessionStateBehavior = _controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);  
  14.         requestContext.HttpContext.SetSessionStateBehavior(sessionStateBehavior);  
  15.           return new MvcHandler(requestContext);  
  16.     }  
  17. }  

在用于提供HttpHandler的GetHttpHandler方法中,除了返回一個實現了IHttpHandler接口的MvcHandler對象之外,還需要對當前HTTP上下文的會話狀態行為模式進行設置。具體來說,首先通過包含在傳入RequestContext的RouteData對象得到Controller的名稱,該名稱連同RequestContext對象一起傳入ControllerFactory的GetControllerSessionBehavior方法得到一個類型為SessionStateBehavior的枚舉。***通過RequestContext得到表示當前HTTP上下文的HttpContextBase對象(實際上是一個HttpContextWrapper對象)并調用其SetSessionStateBehavior方法。

紹我們知道RouteData中的RouteHandler屬性最初來源于對應的Route對象的同名屬性,而當我們調用RouteCollection的擴展方法MapRoute方法時,其內部會直接創建并添加一個Route對象。由于在創建Route對象是并沒有顯式指定ControllerFactory,所以通過當前ControllerBuilder的GetControllerFactory方法得到的ControllerFactory默認被使用。

通過當前ControllerBuilder的GetControllerFactory方法得到的ControllerFactory僅僅用于獲取會話狀態行為模式,而MvcHandler真正將它用于創建Controller。MvcHandler中關于對請求處理的邏輯基本上可以通過如下的代碼片斷來體現。如下面的代碼片斷所示,MvcHandler具有一個表示當前請求上下文的RequestContext屬性,該屬性在構造函數中被初始化。

  1. public class MvcHandler : IHttpHandler  
  2. {  
  3.     public RequestContext RequestContext { getprivate set; }  
  4.    public bool IsReusable  
  5.     {  
  6.         get { return false; }  
  7.     }  
  8.    public MvcHandler(RequestContext requestContext)  
  9.     {  
  10.        this.RequestContext = requestContext;  
  11.    }  
  12.    public void ProcessRequest(HttpContext context)  
  13.    {  
  14.        IControllerFactory controllerFactory = ControllerBuilder.Current.GetControllerFactory();  
  15.        string controllerName = this.RequestContext.RouteData.GetRequiredString("controller");  
  16.        IController controller = controllerFactory.CreateController(this.RequestContext, controllerName);  
  17.       try 
  18.        {  
  19.            controller.Execute(this.RequestContext);  
  20.        }  
  21.        finally 
  22.       {  
  23.           controllerFactory.ReleaseController(controller);  
  24.       }  
  25.    }  
  26. : } 

在ProcessRequest方法中,通過RequestContext對象得到目標Controller的名稱,并通過它利用當前ControllerBuilder創建的ControllerFactory激活Controller對象。在執行了被激活Controller對象的Execute方法之后調用ControllerFactory的ReleaseController對其進行釋放清理工作。

原文鏈接:http://www.cnblogs.com/artech/archive/2012/03/31/controller-activation-01.html

【編輯推薦】

  1. ASP.NET MVC3 從零開始一步步構建Web
  2. Node.js vs Opa: Web框架殺手
  3. 設計好脾氣的Web頁面
  4. Google Web App開發指南之構建優秀的Web Apps
  5. 如何解決IndexedDB在webkit內核下新舊版本的兼容問題

 

責任編輯:彭凡 來源: 51CTO
相關推薦

2013-09-02 17:46:41

MVC架構設計MVC架構設計

2010-03-19 09:17:16

ASP.NET MVC

2009-09-18 10:20:26

PRG數據驗證

2023-07-03 08:48:40

Web模塊化設計

2009-07-24 13:20:44

MVC框架ASP.NET

2011-04-18 09:35:59

ASP.NET MVC

2009-07-31 12:43:59

ASP.NET MVC

2009-09-10 09:50:47

ASP.NET MVC

2010-10-12 09:52:02

ASP.NET MVC

2009-10-29 09:15:32

ASP.NET MVCDropDownLis

2009-07-24 11:55:29

ASP.NET MVC

2009-07-29 16:08:07

ASP和ASP.NET

2009-07-22 10:09:59

ASP.NET MVC

2009-07-23 15:44:39

ASP.NET MVC

2009-07-23 14:31:20

ASP.NET MVC

2009-07-22 13:24:24

ASP.NET MVC

2009-07-20 10:53:59

ASP.NET MVC

2009-12-11 09:36:50

ASP.NET MVC

2011-04-14 09:19:22

ASP.NET MVC

2017-03-06 11:13:57

ASP.NETCoreMVC
點贊
收藏

51CTO技術棧公眾號

亚洲天堂网在线视频| 男女性杂交内射妇女bbwxz| 成年人在线看| 精彩视频一区二区| 欧美精品在线网站| 国产高清自拍视频| 日本午夜免费一区二区| 亚洲一级二级在线| 欧美精品中文字幕一区二区| 中文字幕777| 亚洲视频精品| 自拍偷拍亚洲精品| 国产 xxxx| 日韩有码欧美| 夜色激情一区二区| 欧美一区2区三区4区公司二百| 国产精品欧美综合亚洲| 亚洲在线视频| 久久国产精品99国产精| 扒开jk护士狂揉免费| 6080亚洲理论片在线观看| 一本色道亚洲精品aⅴ| 日韩国产精品毛片| 黄色片在线免费看| 懂色av一区二区在线播放| 国产精品99久久久久久人| 久久久久无码国产精品不卡| 精品国产91乱码一区二区三区四区| 欧美一区二区三区免费视频 | 欧美高清视频www夜色资源网| 青青草国产精品视频| 黄网站免费在线播放| 久久久精品中文字幕麻豆发布| 91香蕉视频在线下载| 国产亚洲久一区二区| 亚洲激情欧美| 久久99久久99精品免观看粉嫩| 精品人体无码一区二区三区| 在线亚洲a色| 亚洲级视频在线观看免费1级| 中文字幕第六页| 国产原创一区| 色噜噜狠狠成人网p站| 黄色大片中文字幕| 欧美男男video| 综合久久给合久久狠狠狠97色| 欧美一区二区三区电影在线观看| 天天躁日日躁狠狠躁伊人| 粉嫩在线一区二区三区视频| 91手机视频在线观看| 一级黄色a视频| 奇米综合一区二区三区精品视频| 国产成人精品最新| 无码人妻丰满熟妇奶水区码| 国产精品亚洲欧美| 91成品人片a无限观看| 久草网在线观看| 欧美日韩综合| 久久久亚洲精选| 亚洲国产精品成人无久久精品| 亚洲午夜极品| 久久久久久久久久久av| 日韩欧美中文字幕一区二区| 亚洲激情影院| 欧美中文字幕视频在线观看| 岛国av中文字幕| 奇米影视在线99精品| 成人福利视频在线观看| 国产乱淫av片免费| 国产精品影音先锋| 国产精品一级久久久| 亚洲日本中文字幕在线| 国产日韩欧美一区二区三区乱码| 亚洲永久一区二区三区在线| 麻豆传媒在线免费| 亚洲综合一二三区| 国产精品va无码一区二区| 欧美xxxx做受欧美护士| 欧美精品在线视频| 日本女人黄色片| 国语一区二区三区| 国产亚洲a∨片在线观看| 黑人操日本美女| 极品日韩av| 青草热久免费精品视频| 久久无码精品丰满人妻| 亚洲国产一区二区三区a毛片| 97久久伊人激情网| www五月天com| 激情亚洲综合在线| 国产在线精品一区二区中文 | 亚洲青青一区| 欧美不卡一区二区| 亚洲国产综合视频| 精品国产乱码久久久久久1区2匹| 伊人久久久久久久久久久| jizzjizzjizz国产| 亚洲特色特黄| 国产精品久久久久久网站| 亚洲成人中文字幕在线| 91视频一区二区| 午夜精品短视频| 18+视频在线观看| 精品久久久久久中文字幕| 日本女优爱爱视频| 成人国产精品久久| 亚洲高清久久网| 天堂资源在线视频| 欧美视频福利| 国产成人一区二区三区电影| 国产一区二区麻豆| caoporn国产一区二区| 日本一区二区在线视频观看| 日本黄色片在线观看| 亚洲最大色网站| 国产v亚洲v天堂无码久久久| 美女日韩一区| 亚洲一级一级97网| 久久精品视频9| 亚洲一区二区免费看| 成人黄色大片在线免费观看| 好吊视频一二三区| 国产精品天美传媒沈樵| 超碰成人免费在线| 成人在线视频免费| 亚洲精品在线91| 欧美成人精品欧美一| 亚洲欧美日韩精品一区二区| 91网站在线免费观看| 手机福利小视频在线播放| 自拍偷拍欧美精品| 欧美午夜性生活| 欧洲精品99毛片免费高清观看| 尤物九九久久国产精品的特点 | 亚洲欧美tv| 欧美多人乱p欧美4p久久| 日本精品入口免费视频| 97成人超碰视| 免费的av在线| 黄页免费欧美| 亚洲毛茸茸少妇高潮呻吟| 欧美成人精品一区二区免费看片| 奇米777欧美一区二区| 国产一级精品aaaaa看| 中文国产字幕在线观看| 5月丁香婷婷综合| 国产精品麻豆一区| 石原莉奈在线亚洲三区| 精品麻豆av| 黄色小说在线播放| 欧美一级日韩不卡播放免费| av资源在线免费观看| av成人黄色| 奇米精品在线| 欧美电影免费观看网站| 亚洲精品成人久久电影| 精品一区免费观看| 国产成人亚洲综合a∨婷婷图片| 四虎影院一区二区| 婷婷激情成人| 亚洲日本中文字幕| 日韩xxx视频| 日本一区二区三区国色天香| 欧美日韩亚洲第一| 一本久久青青| 国产精品成久久久久三级| 三级无遮挡在线观看| 欧美日韩亚洲高清| 中文字幕在线视频播放| 午夜一区在线| 日韩在线三级| av成人在线看| 最近2019中文字幕一页二页 | 日本一本在线视频| 欧美日本一区二区高清播放视频| 91视频国产高清| 日本无删减在线| 精品久久久久久久久久久久包黑料| 538任你躁在线精品视频网站| 国产一区二区三区不卡在线观看| 香蕉视频免费版| 国产精品亚洲一区二区在线观看| 欧美大片在线影院| 瑟瑟在线观看| 欧美丝袜自拍制服另类| 污污视频网站在线免费观看| 狠狠色丁香婷婷综合| 麻豆映画在线观看| 激情视频极品美女日韩| 久久久久日韩精品久久久男男| 欧美在线一卡| 欧美调教femdomvk| 九九九久久久久| 91日韩在线专区| 999精彩视频| 综合一区av| 激情伦成人综合小说| 激情中国色综合| 色综合久久88| 日韩精品系列| 777午夜精品免费视频| 精品在线视频观看| 国产调教视频一区| 天天操狠狠操夜夜操| 性xx色xx综合久久久xx| 一区二区三区av| 国产精品qvod| 国产剧情久久久久久| gogo高清在线播放免费| 亚洲视频在线观看网站| 精品人妻av一区二区三区| 日本精品视频一区二区三区| 日韩va亚洲va欧美va清高| 97国产精品videossex| 狠狠干狠狠操视频| 亚洲综合国产激情另类一区| 在线观看欧美激情| 一区二区亚洲视频| 91亚洲一区精品| 国产高清不卡| 欧美激情xxxx性bbbb| 成人免费高清在线播放| 日韩免费观看高清完整版| 无码人妻精品一区二| 一区二区三区美女视频| 免费看的黄色录像| xf在线a精品一区二区视频网站| 能看的毛片网站| 亚洲视频中文| 一级黄色免费在线观看| 国产麻豆精品久久| 国产美女精品久久久| 日韩免费大片| 日韩av电影国产| 成人一区福利| 久久久噜噜噜久久久| 黄色网在线看| 尤物99国产成人精品视频| 色在线免费视频| 欧美一区二区私人影院日本| 亚洲在线精品视频| 在线亚洲高清视频| 国产无遮挡呻吟娇喘视频| 亚洲一区二区中文在线| 男女做暖暖视频| 亚洲欧洲日本在线| 中文乱码字幕高清一区二区| 国产日本欧美一区二区| 国产黄色网址在线观看| 99久久精品免费精品国产| 苍井空张开腿实干12次| 久久66热偷产精品| 九九热视频免费| 狠狠色狠狠色综合系列| 欧美女同在线观看| 蜜臀av一级做a爰片久久| 久久网站免费视频| 99riav国产精品| 成人小视频在线看| 香蕉亚洲视频| 久久久久久久久久久久久国产精品| 在线不卡视频| 青草青青在线视频| 国产精品永久| 国产1区2区在线| 久久精品日产第一区二区| 国模杨依粉嫩蝴蝶150p| 每日更新成人在线视频| 日本www在线播放| 免费成人你懂的| www.浪潮av.com| 日本中文一区二区三区| 国产日韩欧美久久| 久久五月激情| 国产精品欧美激情在线观看| 噜噜爱69成人精品| 国产精品又粗又长| 毛片一区二区| 日韩在线xxx| 人人超碰91尤物精品国产| 玖玖爱视频在线| 国产精品99久久久久久久女警| 国产成人精品一区二区在线小狼| 丁香天五香天堂综合| 巨乳女教师的诱惑| 99久久精品国产观看| 国产人妻大战黑人20p| 久久久久九九视频| 男人av资源站| 天天色综合成人网| 91porny九色| 欧美一区二区三区免费大片 | 亚洲一级片在线看| 黄av在线播放| 国外视频精品毛片| 亚洲mmav| 含羞草久久爱69一区| 精品国产一区二区三区四区| 中文字幕在线亚洲精品| 国产一区久久| 男人舔女人下面高潮视频| 毛片基地黄久久久久久天堂| www日本在线观看| 久久久99精品久久| 成熟的女同志hd| 第一福利永久视频精品| 国产精品国产av| 日韩成人高清在线| 麻豆视频在线| 欧美性视频网站| 国产免费区一区二区三视频免费| 欧美三级网色| 午夜欧美精品| 久久久久久三级| 高清不卡在线观看av| 精品无码在线视频| 亚洲国产精品久久久久婷婷884| 波多野结衣午夜| 精品久久久久久久久久久久久久久 | 免费在线视频一级不卡| 精品国产一区二区在线| 秋霞在线视频| 亚洲最大的免费| 欧美精选视频在线观看| 日本xxxxxxxxxx75| 国产一区二区三区在线看麻豆| 国产精品久久久久久成人| 亚洲一区二区三区三| 在线免费看av的网站| 日韩高清免费在线| 在线h片观看| 91久久极品少妇xxxxⅹ软件| 欧美日韩在线观看视频小说| 2018国产在线| 国产成人在线免费观看| 波多野结衣一二三四区| 日本乱码高清不卡字幕| 无码精品在线观看| 欧美激情乱人伦| 欧美影院在线| 国产成人亚洲综合无码| 国内精品国产成人| 一二三四在线观看视频| 色老汉一区二区三区| 免费av网站观看| 久久久久久久国产精品视频| 视频二区欧美毛片免费观看| 亚洲日本japanese丝袜| 视频一区国产视频| www.涩涩爱| 欧美日韩亚洲综合在线 欧美亚洲特黄一级| 视频一区二区三区在线看免费看| 国产+人+亚洲| 秋霞影院一区| 日本香蕉视频在线观看| 国产大片一区二区| 日韩一级片av| 日韩欧美www| 爱啪视频在线观看视频免费| 国产精品香蕉视屏| 亚洲精品美女91| 亚洲调教欧美在线| 欧美日韩亚洲一区二区| 十九岁完整版在线观看好看云免费| 97精品一区二区视频在线观看| 波多野结衣欧美| 日本福利视频一区| 久久蜜桃香蕉精品一区二区三区| 免费av网站在线| 亚洲午夜av久久乱码| 日本在线中文字幕一区二区三区| 亚洲日本一区二区三区在线不卡| 美日韩一区二区| 天天色影综合网| 337p日本欧洲亚洲大胆精品| xxxxxx欧美| 日韩免费av一区二区三区| 久久久夜夜夜| 国产又黄又粗又猛又爽的| 日韩色视频在线观看| 成年人国产在线观看| 久久99国产精品99久久| 日韩极品在线观看| 最新一区二区三区| 亚洲国产另类久久精品| 欧美大胆性生话| 影音先锋成人资源网站| 国产成人av资源| 精品不卡一区二区| 亚洲视频日韩精品| 99久久免费精品国产72精品九九| 成人免费观看cn| 国产女同互慰高潮91漫画| 最近中文字幕av| 韩剧1988在线观看免费完整版 | 久久99精品国产99久久| 日韩精品国产精品| 日本黄色录像视频| 亚洲精品网址在线观看| 91嫩草国产线观看亚洲一区二区 |