MVC5-2 MVC的管道流與路由

自定義Modue與Hander

以前講了管道流中的Module與Hndler。如今咱們能夠去自定義Module和Handler web

Module

其實很簡單,一共須要三個步驟 緩存

  • 定義一個類去繼承IHttpModule。並實現接口,這裏推薦類以Module結尾
  • 在Init方法中註冊咱們所須要的事件,完成攔截器。
  • 在WebConfig的System.webServer節點中配置Modules

clip_image001

clip_image002

Handler

和自定義Module相似 app

  • 建立一個類去繼承IHttpHandler接口,並實現接口。
  • 在ProcessRequest中進行作咱們須要的處理
  • 在WebConfig的system.webServer節點中配置hanlder

clip_image003

clip_image004

注:MVC也是這麼去作的,註冊了Mvc的Module和Mvc的Handler。 函數

 

MVC管道

MVC的路由也是經過Module去攔截,而後找到匹配的路由。而後拿到handler激活Controller。下面解析一下過程 this

在MVC中咱們在RouteConfig中配置路由。結構是這樣的 url

clip_image005

那麼截獲它的是UrlRoutingModule => spa

=> 這個moudule如咱們自定義的同樣,繼承了IHttpModule。註冊了事件 application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);。須要說明的 是,這裏也有了緩存。只有第一次纔會去執行 3d

clip_image006

=> RouteData routeData = this.RouteCollection.GetRouteData(context); 映入眼簾的是這段代碼。GetRouterData就是去獲取匹配的路由 blog

clip_image007

=> 而後看到了一個foreach,是的。foreach。按照個人觀察,它是一個鍵值對。這裏就知道了,爲何經常使用的路由要放到前面。能夠快速遍歷到。這裏的值是RouteBase,它是一個抽象類。具體的實現應該在子類裏面。 繼承

clip_image008

=> 繼續會看到,獲取了RouteHandler!。那麼RouteHandler是什麼呢。

clip_image009

=> 轉到了MapRoute也就是咱們的定義路由方法,看到了一個MvcRouteHandler。再轉到Route的構造函數

clip_image010

clip_image011

=> 能夠看到他是一個IRouteHandler的實現!以前Module的圖繼續往下走,看到了調用了GetHttpHandler這個方法。能夠看到其實它就至關於一個工廠。那麼拿到的又是什麼呢

clip_image012

=> 能夠發現,返回了一個MvcHandler。它就是咱們的最終主角。這時候一系列操做就完成了,MvcHandler的ProcessRequest方法,下圖是同步方法,這裏拿到了IController。而後再Execute。 IController是ControllerBase類繼承的接口,Execute中又調用了ExecuteCore方法。也就是Controller類的實現。到此管道結束

clip_image013

clip_image014

clip_image015

這張圖就是MVC的管道總體流程

clip_image016

 

Route詳解

咱們在定義了MapRoute後,到底放到了什麼地方呢?又是怎麼對值進行過濾的呢?道兄莫慌,下面一一分析。

注意,這裏並無實踐。由於斷點一直下不去。因此引用了別人的圖。待以後再實踐吧

clip_image017

上圖不難發現,除了MapRoute外還有IngoreRoute。 進入到Blobal中能夠看到註冊路由用的是RouteTable.Routes

RouteTable

=> Routes [RouteCollection]

先看MapRoute的建立

先是建立一個Route而後添加到了咱們的 routes [RouteCollection]中

Route route = new Route(url, new MvcRouteHandler()) {

Defaults = CreateRouteValueDictionaryUncached(defaults),

Constraints = CreateRouteValueDictionaryUncached(constraints),

DataTokens = new RouteValueDictionary()

};

ConstraintValidation.Validate(route);

if ((namespaces != null) && (namespaces.Length > 0))

{

route.DataTokens["Namespaces"] = namespaces;

}

routes.Add(name, route);

而後再去看IgnoreRoute的建立

是的沒錯。這裏建立一個IgnoreRouteInternal,而後也添加到了Routes中。

IgnoreRouteInternal route = new IgnoreRouteInternal(url) {

Constraints = CreateRouteValueDictionaryUncached(constraints)

};

ConstraintValidation.Validate(route);

routes.Add(route);

那麼問題來了,MVC是如何分別受支持和不被支持的路由呢?

還記得,咱們的Route的構造函數須要一個IRouteHandler。這個IgnoreRouteInternal則是Route的子類,那麼它傳入的是什麼呢?

clip_image018

能夠看到,是StopRoutingHandler,這就不難猜到了。回到UrlRoutingModule代碼中,從下圖能夠發現,這裏拿到了RouteHandler以後,進行了判斷。若是是StopRoutingHandler則直接把請示打回去。

clip_image019

下面開始說參數驗證,

MapRoute有幾個重載,有這樣一個參數,contraints。它能夠對咱們的參數進行一些約束。

clip_image020

一個簡單的玩法,這裏對id這個參數進行了約束,使其必須是數字。不只是id,其它的片斷也能夠進行約束。

clip_image021

看一下源碼,其實這個方法就是進行匹配。在ProcessConstraion中,拿到了IRouteConstrraint。若是咱們的表達式是strng,就進行正則匹配。

上面有一個Match。這個是最吊的自定義。

clip_image022

clip_image023

進行自定義約束玩玩

  • 須要繼承自IRouteConstraint接口,並實現
  • 在MapRoute對參數進行傳入約束實例

clip_image024

clip_image025

相關文章
相關標籤/搜索