2012年11月22日 星期四

ASP.Net MVC中的Route

image

        在之前的文章中曾經探討過各個MVC專案中的資料夾內容,當時對於App_Start這個資料夾僅是淺淺的帶過去,而本篇文章開始將會一個個介紹這個資料夾中的所有檔案,原因無它,因為這個資料夾中的所有檔案對於未來開發MVC專案來說都是極為重要的檔案。

        在MVC中,除去View Model Controller這幾位主角之外,另外一位舉足輕重的就是Routing。其道理很簡單,因為一個使用者的Request要如何正確且精準的被服務對於網站來說是極其重要的,總不能使用者希望看到A網頁但是網站卻回傳一個B網頁給使用者。

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id =     UrlParameter.Optional }
            );
        }
    }
在App_Start這個資料夾中的RouteConfig.cs,其內容如上面程式所述,這是一個極短的程式碼。就讓我們一行行的解析這段程式碼所達成的功能以及其中的關竅。

      RouteConfig這個類別裡面只有一個方法:RegisterRoutes,這是一個靜態方法;亦即,使用這個方法的物件不需要特別將這個類別實體化,可以直接以 RouteConfig.RegisterRoutes呼叫它。究其方法內容,我們可以將其分成兩個部份來看,一者為規避,另一者為設定。

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

這段程式碼在描述: 任何以axd結尾並且後續任何串接路徑都不予以理會。舉個例來說:
      http://localhost/Hello.axd/world/You/
       上述這段網址正好符合了{resource}.axd/{*pathInfo}這種Url格式。其實,無論是resource或是pathInfo,這兩個其實都是一個變數而已,本身並不具有什麼特別的意義;以上述的Url來說,我們可以看成
       resource => Hello
      *pathInfo => world/You/

      pathInfo這個變數前面的*號代表著無論有多少個,所以Hello後面無論有多少個都會被視為pathInfo的一部份。再來我們要探討為什麼要忽略符合這個格式的Request呢?其實,在IIS上面除了MVC的網站專案之外,其餘還有非常多的網站也會掛在上面,因此,如果沒有特別去過濾勢必會造成這些網站的Request被Route給誤導了。

      再來就是談談Routing的設定, RegisterRoutes這個方法第二個部份就是在進行路由的設定。

routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
上面這段程式碼的功能其實很簡單,就是在比對符合{controller}/{action}/{id}這種Url格式的Request該被那個Controller的那個Action服務。舉例來說:

     http://localhost/Home/Index

    這段的解析如下:
    controller => Home
    action => Index

   大家會很好奇,那id去那了?可以翻遍了整個Url來看就是整不到可以與id對上的,難道id不存在?
   是的,就我上面所舉的那個Url來說,id確實不存在。再特別提到一點,上面所舉的Url的例子其實與 http://localhost/ 是完全等價的。其原因我們再繼續看MapRoute這個API的第三個參數:

defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

   defaults這個參數在描述著,若Url沒有提供controller則預設會帶入"Home"作為預設值,而action的預設值則為"Index",如此一來就解釋了為什麼我說 http://localhost/Home/Index 會與 http://localhost  等價了。再來,還要再解釋id的問題。其實,在defaults這個參數中已經言明 id其實是個選擇性的(Optional),因此,id可有可沒有,這完全都不會影響到Url的判斷。

總結:Route對於MVC來說是一門很重要的必修課,因為,再好的MVC設計如果無法讓使用者的Request正確導向正確的Controller,這很容易就會造成使用者明明要的是A網頁,但是網站全傳回B網頁給他。

1 則留言: