天天看點

【轉】Asp.Net MVC4 之Url路由

MVC4常見路由的處理方式

先來看下面兩個個url,對比一下:

http://xxx.yyy.com/Admin/UserManager.aspx

http://xxx.yyy.com/Admin/DeleteUser/1001 

   對于第1個Url,假設它與伺服器上的檔案有直接的關系,那麼伺服器在接受用戶端請求并将對應的檔案傳送給用戶端。我們大概可以猜到它是對使用者管理的一個頁面,它的實體檔案UserManager.aspx在網站根目錄下面的Admin檔案夾中。而第2個url,在不知道Mvc路由以及Url重寫時,很難猜到這個Url背後具體有些什麼,前提條件是基于.Net架構開發的Web項目。 那麼在這裡,我們引入Asp.Net Mvc Url路由這個概念,也正是本文所要闡述的主題,Url路由子產品是負責映射從浏覽器請求到特定的控制器動作。

  基于上面提到的Url路由以及其作用,我們就大概能猜到第2個Url背後有些啥了。 自然而然的Admin就是控制器了,DeleteUser是控制器裡面的動作及Action了,1001就是Action的參數。到這裡我們對Url路由有一個簡單的認識,那麼接着看下面一組url,假設Home是控制器,Index是控制器裡面的Action,至于1001或者2345這類資料我們暫且約定為參數:

http://xxx.yyy.com

http://xxx.yyy.com/Home/1001

http://xxx.yyy.com/Index/1001

http://xxx.yyy.com/Home/Index/1001/2345

http://xxx.yyy.com/System/Home/Index/1001

按照約定,從上面的幾組Url中可以看出,有的缺控制器,有的缺Action,有的帶有好幾個參數,有的又莫名的多出了控制器、Action、參數之外的東西,那麼他們能正确的通路嗎?

  注冊路由

    在vs2012裡面建立一個asp.net mvc4 web 應用程式項目,可以在項目的根目錄下App_Start裡面看到RouteConfig檔案,在這個檔案裡面就可以添加url路由了。在檔案裡面可以看到MapRoute 這個方法,它是RouteCollection的擴充方法,并且含有多個重載,下面看看MapRoute方法的參數,這裡選參數最多的那個:

從上面的代碼片段大概可以看出該方法含有路由名稱、路由的Url、預設值、限制、首先查找路由所在的命名空間,該方法是傳回對映射路由的引用。不過在RouteConfig檔案中我們可以看到添加路由的代碼:

稍微分析一下這段代碼可以知道,在路由集合裡面添加了一個名為"Default"的路由,并且有一個預設的路由指向,指向名稱為Home的控制器,并且Action為Index,可以明顯的看到這裡 "id = UrlParameter.Optional" 的寫法,它的意思就是說Action的參數可以不需要使用者來指定,可以預設。

  多個參數如何傳遞

  之前在一個QQ群裡面見到一兄弟在問,類似這樣的Url“http://xxx.yyy.com/Home/Index/1001/2345/tauruswu”在路由裡面怎麼配置?其實這個也很簡單,我們隻需要将路由配置、以及Action稍作調整。

這個是調整之後的路由配置,隻需要在Url後面再加上"{*catchall}"即可,那麼Action調整之後如下

在Action裡面定義了一個參數"catchall"用來接收Url中除了Id之外其他所有的參數值,那麼上面那個Url中接收的參數就是“2345/tauruswu”,這樣看起來好不好了,不過我覺得怪怪的,有沒有更好的解決方法了?Url有必要寫成那麼長嗎?這個問題在後續文章中會涉及到。

  你也許會犯的錯誤

  不知各位兄弟在剛剛接觸MVC的時候,有沒有碰到過這樣的問題,如下圖

【轉】Asp.Net MVC4 之Url路由

那麼這個錯誤是如何引起的了?代碼是這麼寫的

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

我們再看英文提示大概就是說比對出了多個控制器為"Home"的類型,在它的提示中也告訴了我們解決方法,說在MapRoute方法中使用"namespaces"這個參數,我們先将這個放在一邊,将抛出這個錯誤的源碼給找出來,具體的源碼在DefaultControllerFactory這個類中,看類名就能猜出它的作用是什麼了。

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

上面粗體标出的代碼,因為我們在路由中沒有配置“namespaces”這個參數,這段代碼的意思就是通過控制器名稱擷取所比對的控制器類型集合,當擷取到集合資料之後就開始Case了,很明顯,這裡集合的數目是2,自然就抛錯了。

  問題出來了,該如何解決?在錯誤提示中說要用到“namespaces”這個參數,我們能不能告訴MVC解析引擎,在解析控制器名稱時,能不能對某些命名空間進行優先處理,事實上是可以的,隻需要在配置路由的地方稍微調整一下

上面标粗的代碼的意思是說優先解析“MvcDebug.Controllers.Tauruswu”這個命名空間裡面的控制器。

  路由限制

  對于路由限制,我個人覺得這個可能在實際開發中用的不是很多,既然MapRoute方法提供了constraints這個參數及限制,那麼在某些特定的場合肯定能發揮它的作用。在MVC中提供了三種路由限制方案,分别是: 1)正規表達式 ,2)http方法 ,3)自定義限制 。下面我們分别介紹下這三種限制的使用方法。

  1)正規表達式 ,在路由配置中,我們做了這樣的規則,隻比對Controller名稱以H開頭的

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

  2) http方法 ,我們将路由配置稍作修改

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

然後在對應的Action上面打個标記

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

你們說這樣行不行了?

   3) 自定義限制,如果說上面兩種需求還是不能滿足你,那麼我們可以自定義限制。我們翻看HttpMethodConstraint這個類,可以看到它是繼承IRouteConstraint這個接口,其定義是

裡面隻有一個布爾類型的方法,關于這個例子,是從網上借鑒過來的,如下

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

這段代碼的意思就是檢查用戶端請求的UserAgent屬性值,看它是否含有一個被傳遞給構造函數的值。那麼我們将路由作如下修改

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

很顯然,這個隻能在IE遊覽器下面遊覽。

  如何建立自定義路由處理程式

  在翻閱MapRoute方法源碼的時候,看到了這麼一段

【轉】Asp.Net MVC4 之Url路由
【轉】Asp.Net MVC4 之Url路由

在Route執行個體化的時候,它是用到了“MvcRouteHandler“這個類,該類繼承”IRouteHandler“接口,如果我們不用系統裡面已經定義好的路由處理方案,我們要自己來實作一套?改怎麼下手,此時隻需要繼承”IRouteHandler“這個接口并實作”GetHttpHandler“方法即可。

   最後在添加路由時,像這樣操作

當我們在遊覽器裡面請求/DemoUrl這個位址時,就會用到我們自定義的處理程式,在實際開發當中,如果真的要用到自定義路由處理程式,那麼我們就要實作很多原本架構所實作的空能,雖然這給我們帶來了很大的擴充空間,但是又不可控。

  總結

  Url路由系統是通過請求位址進行解析進而得到以目标Controller/Action名稱為核心的路由資料,Url路由系統是建立在Asp.net 之上,我們在調試System.Web.Routing的源碼時候可以得知。在這裡我們由淺入深的了解了路由系統,接下來我們會講到控制器以及Action,也是最為核心的東西。

學習交流群:364976091

繼續閱讀