0%

【MVC教學】3. Route(一)

什麼是Route 在現實生活中比較接近於郵差與地圖的關係,你將想要送的東西交給郵差,郵差依據包裹上的地址,透過地圖找到目的地然後投遞。

而對應到程式中[網址]就是你包裹要送達的目的地址,Route就是[地圖],而網址的[參數]就是你要投遞的包裹

[![](https://4.bp.blogspot.com/-v_OpLGzjdtw/Wq0MHMSi2mI/AAAAAAAAIko/7mcxcoPLkpUWExDOSn657rGCjMfUtiJSgCLcBGAs/s400/1.jpg)](https://4.bp.blogspot.com/-v_OpLGzjdtw/Wq0MHMSi2mI/AAAAAAAAIko/7mcxcoPLkpUWExDOSn657rGCjMfUtiJSgCLcBGAs/s1600/1.jpg)
接著我們來看看專案內的Route在哪邊設定,又它是如何透過網址知道該把[包裹]送去哪支程式的,這邊先把我們之前的專案執行起來,並且點擊[關於]
[![](https://1.bp.blogspot.com/-ryN1Z3Mp3SI/Wq0MU9PT8mI/AAAAAAAAIks/ONCnMFBGRhYG0YWmLnZUV__5jGS5gpBBgCLcBGAs/s400/2.png)](https://1.bp.blogspot.com/-ryN1Z3Mp3SI/Wq0MU9PT8mI/AAAAAAAAIks/ONCnMFBGRhYG0YWmLnZUV__5jGS5gpBBgCLcBGAs/s1600/2.png)
可以看到關於頁的網址為 /Home/About
[![](https://4.bp.blogspot.com/-F1fHYAInGic/Wq0MkAgp4uI/AAAAAAAAIkw/PN3nKltrc5wH8Lkb9Lk5_6flzLCy80GOACLcBGAs/s400/3.png)](https://4.bp.blogspot.com/-F1fHYAInGic/Wq0MkAgp4uI/AAAAAAAAIkw/PN3nKltrc5wH8Lkb9Lk5_6flzLCy80GOACLcBGAs/s1600/3.png)
接著我們在HomeControllerAbout下中斷點後再點擊一次網頁的[關於]按鈕,會發現程式停在我們下中斷點的地方了? 為什麼知道程式會跑到這邊呢 ? 這一切都是因為有Route指路的關係
[![](https://1.bp.blogspot.com/-LFueIPKzOYI/Wq0MwArDFLI/AAAAAAAAIk4/gJdWivFruxcZoCKaGNAfYamVnM8JEO3igCLcBGAs/s400/4.png)](https://1.bp.blogspot.com/-LFueIPKzOYI/Wq0MwArDFLI/AAAAAAAAIk4/gJdWivFruxcZoCKaGNAfYamVnM8JEO3igCLcBGAs/s1600/4.png)

RouteConfig

Route的規則是可以自己制訂的,而制定的地方就在App_Start資料夾底下的RouteConfig裡面
[![](https://2.bp.blogspot.com/-empHw_-1tig/Wq0M_p2kL-I/AAAAAAAAIlA/XQjsx0UahlsjJyqijDxTtSa7hmnkJVm5ACLcBGAs/s400/5.png)](https://2.bp.blogspot.com/-empHw_-1tig/Wq0M_p2kL-I/AAAAAAAAIlA/XQjsx0UahlsjJyqijDxTtSa7hmnkJVm5ACLcBGAs/s1600/5.png)
[![](https://3.bp.blogspot.com/-r4pEpAts3NA/Wq0NBNPYBKI/AAAAAAAAIlE/rUslCqFTfUEvvPRAG5cWKdDvL8S_CgGGQCLcBGAs/s400/6.png)](https://3.bp.blogspot.com/-r4pEpAts3NA/Wq0NBNPYBKI/AAAAAAAAIlE/rUslCqFTfUEvvPRAG5cWKdDvL8S_CgGGQCLcBGAs/s1600/6.png)
讓我們來解讀這段程式碼,首先routes.MapRoute就是註冊地址的方法,裡面有幾個參數分別為
Name : 你對於這個Route的命名
Url : 網址條件,當網址符合這個條件特徵時,就會依據這個Route的指示去找對應執行的程式碼
defaults : 參數的預設值
相信光是講解參數的意義對於要理解Route還有相當的距離,讓我們直接來實戰理解 /Home/About這串網址如何對應到Route的吧,剛剛有說,routes.MapRouteUrl參數是用來判斷網址特徵是否相符,如果相符就會被這串Route捕捉到,但是這兩個怎麼看都不像啊
真實網址 /Home/About
Route Url :  {controller}/{action}/{id}
首先必須先知道一件事情,當Route Url的網址用{ }包起來的時候,代表他是個變數,什麼是變數?變數是一個表示值,它可以是任意的值,而{}裡面的字就是變數的名稱,以上述例子為例
我們有一個變數叫做controller,它可以是任意的值
我們有一個變數叫做action,它可以是任意得值
我們有一個變數叫做id,它也可以是任意的值
那套入/Home/About會變成什麼結果?
我們有一個變數叫做controller,它現在的值是Home
我們有一個變數叫做action,它現在的值是About
我們有一個變數叫做id,它現在沒有值
Route的制定中,**controlleraction****為保留字**,意思是告訴他要執行哪個controllerAction,依據這邊的規定,所以它知道要去執行Home這個Controller,裡面一個叫做AboutAction
[![](https://3.bp.blogspot.com/-lPmkR6MJKWs/Wq0NMR-XeJI/AAAAAAAAIlM/NuECRMJtFww8ve031wVUqj-dnCa6K4FQgCLcBGAs/s400/7.png)](https://3.bp.blogspot.com/-lPmkR6MJKWs/Wq0NMR-XeJI/AAAAAAAAIlM/NuECRMJtFww8ve031wVUqj-dnCa6K4FQgCLcBGAs/s1600/7.png)

在Controller裡面寫的方法我們稱之為Action,而他通常都會回傳ActionResult

再讓我們看一個例子 [首頁]
首頁的網址為 : http://localhost:54004/
[![](https://1.bp.blogspot.com/-l2A_55syPtg/Wq0NzWKrZFI/AAAAAAAAIlg/NYnq1QMfQBUv9_fsyYczIqUSy4BW4ZHEQCLcBGAs/s400/8.png)](https://1.bp.blogspot.com/-l2A_55syPtg/Wq0NzWKrZFI/AAAAAAAAIlg/NYnq1QMfQBUv9_fsyYczIqUSy4BW4ZHEQCLcBGAs/s1600/8.png)
所以首頁網址等於  
首頁網址 /
Route Url :  {controller}/{action}/{id}
我們有一個變數叫做controller,它現在沒有值
我們有一個變數叫做action,它現在沒有值
我們有一個變數叫做id,它現在沒有值
什麼都沒有,那程式到底要執行哪邊? 這時候Default終於派上用場了,Default的意思就是,當沒有值時,請用我設定的值代替吧
[![](https://1.bp.blogspot.com/-TDgD-ND409Y/Wq0OX06AV7I/AAAAAAAAImc/CSNnXFgp6jkv3ajpzFLwlQuWyC8t7rBUgCEwYBhgL/s400/9.png)](https://1.bp.blogspot.com/-TDgD-ND409Y/Wq0OX06AV7I/AAAAAAAAImc/CSNnXFgp6jkv3ajpzFLwlQuWyC8t7rBUgCEwYBhgL/s1600/9.png)
所以
controller為空值,所以用Default的值代替,所以它的值為Home
action為空值,所以用Default的值代替,所以它的值為Index
id為空直,但Default設定它為UrlParameter.Optional,意思是它是選擇性的,如果沒有沒關係
所以這個Route設定又完美符合了,所以依據條件,我們去HomeControllerIndex下中斷點,試試看進入首頁時是不是會停在這邊
[![](https://2.bp.blogspot.com/-3I8rJaSlSzI/Wq0OT3PebrI/AAAAAAAAIlo/gtyIS1YVuD83WLbI_Fh1huvHCyqCFcwUgCEwYBhgL/s400/10.png)](https://2.bp.blogspot.com/-3I8rJaSlSzI/Wq0OT3PebrI/AAAAAAAAIlo/gtyIS1YVuD83WLbI_Fh1huvHCyqCFcwUgCEwYBhgL/s1600/10.png)
[![](https://3.bp.blogspot.com/-koCX4c7IthY/Wq0OT1iZPOI/AAAAAAAAIls/8Crncjqy5b0piO1OdxXPkaPVzgxpD2pzwCEwYBhgL/s400/11.png)](https://3.bp.blogspot.com/-koCX4c7IthY/Wq0OT1iZPOI/AAAAAAAAIls/8Crncjqy5b0piO1OdxXPkaPVzgxpD2pzwCEwYBhgL/s1600/11.png)
的確,他依據規則跑到了HomeControllerIndex Action了。
那舉一反三一下,換句話說首頁網址也可以是 /Home/Index 摟,試試看,你會發現它的確走到一樣的中斷點
[![](https://2.bp.blogspot.com/-PGK33fEJg-Q/Wq0OT4Pa-7I/AAAAAAAAImo/_9AR8OUt1Iga3IytGl1LuqwTxbsmNeWkwCEwYBhgL/s400/12.png)](https://2.bp.blogspot.com/-PGK33fEJg-Q/Wq0OT4Pa-7I/AAAAAAAAImo/_9AR8OUt1Iga3IytGl1LuqwTxbsmNeWkwCEwYBhgL/s1600/12.png)
你可能會說,那這樣Route還有什麼好學的,這個寫法幾乎萬用了啊? 的確在MVC預設專案中的這個Route設定我們通常稱它為萬用Route,但也因為它幾乎萬用,所以不好管理,所以正常來說都還是會制定自己的Route規則,好方便管理,這個之後慢慢寫專案碰到多了會更有感觸。
接著我們來試著修改一下程式,讓我們的{id}能派上用場吧!!
在剛剛的案例中,因為id設定是Optional所以都沒派上用場,來試試看他怎麼用吧,首先我們先在HomeControllerAbout Action中加入參數id,並且把回傳的訊息改成Your id is (你帶進來的值)
[![](https://3.bp.blogspot.com/-FLI7MLnnMfw/Wq0OUuGGE3I/AAAAAAAAImk/nXWFNqHfTN8NUtq0rDJzxIB1jou_4DAdwCEwYBhgL/s400/13.png)](https://3.bp.blogspot.com/-FLI7MLnnMfw/Wq0OUuGGE3I/AAAAAAAAImk/nXWFNqHfTN8NUtq0rDJzxIB1jou_4DAdwCEwYBhgL/s1600/13.png)
接著我們重新執行一次程式,並且把網址改成/Home/About/Steven
[![](https://2.bp.blogspot.com/-Zks5ZE30New/Wq0OUxoT8HI/AAAAAAAAIms/WxfowIPPItUnVcXErJ1H2FQPfHTWr58RgCEwYBhgL/s400/14.png)](https://2.bp.blogspot.com/-Zks5ZE30New/Wq0OUxoT8HI/AAAAAAAAIms/WxfowIPPItUnVcXErJ1H2FQPfHTWr58RgCEwYBhgL/s1600/14.png)
再練習一次Route比對
我們有一個變數叫做controller,它現在的值是Home
我們有一個變數叫做action,它現在的值是About
我們有一個變數叫做id,它現在的值是Steven
讓接著看中斷點,把滑鼠移到id那的參數會看到,Id依據我們下的網址,以Steven帶進來了
[![](https://3.bp.blogspot.com/-h6ZLvBxZDRE/Wq0OVDhncjI/AAAAAAAAImo/IL83Kj55bx4EQb6yZg5uz7jkxi9Poyq1QCEwYBhgL/s400/15.png)](https://3.bp.blogspot.com/-h6ZLvBxZDRE/Wq0OVDhncjI/AAAAAAAAImo/IL83Kj55bx4EQb6yZg5uz7jkxi9Poyq1QCEwYBhgL/s1600/15.png)
接著看網頁呈現的成果
[![](https://3.bp.blogspot.com/-4scpot89dZU/Wq0OVopL--I/AAAAAAAAImg/sdGZ1pxWLIMBO-ftiDpWhDA3l2f1tz7XwCEwYBhgL/s400/16.png)](https://3.bp.blogspot.com/-4scpot89dZU/Wq0OVopL--I/AAAAAAAAImg/sdGZ1pxWLIMBO-ftiDpWhDA3l2f1tz7XwCEwYBhgL/s1600/16.png)

練習制定一個屬於我們的Route

看了兩個範例,我們也來制定一個Route規則給自己用吧,而且我們不要用變數的方式。
[![](https://3.bp.blogspot.com/-cOBHu8_QRGw/Wq0OV84UZ2I/AAAAAAAAImo/GhiHQFpeFGkvHHlIju0NPcUDtmSpF9OmQCEwYBhgL/s400/17.png)](https://3.bp.blogspot.com/-cOBHu8_QRGw/Wq0OV84UZ2I/AAAAAAAAImo/GhiHQFpeFGkvHHlIju0NPcUDtmSpF9OmQCEwYBhgL/s1600/17.png)
我們希望有個網址為/tellMe/whoAreYou/{name},且name跟之前的id一樣是個變數,可以由你自己打喜歡的文字來決定,寫完後來試試看這個route可不可行
[![](https://1.bp.blogspot.com/-DviuNDcFiHg/Wq0OWIgZMfI/AAAAAAAAImk/uDokBOMNij0mSGMLcLZsxjp63J7qOdKDwCEwYBhgL/s400/18.png)](https://1.bp.blogspot.com/-DviuNDcFiHg/Wq0OWIgZMfI/AAAAAAAAImk/uDokBOMNij0mSGMLcLZsxjp63J7qOdKDwCEwYBhgL/s1600/18.png)
結果竟然錯了,來看看少了什麼
網址 /tellMe/whoAreYou/steven
Route Url :  /tellMe/whoAreYou/{name}
比對tellMe,符合
比對whoAreYou,符合
比對Name這個變數,現在的值為Steven
然後呢? 有沒有發現即便這邊都比對正確,符合route規則,但我們沒告訴他Controller是誰,Action是誰,程式當然不知道該去執行誰,所以再來改一下,因為我們還沒學到如何建立ControllerAction,所以先用現成的, 導到homeControllerContact
[![](https://1.bp.blogspot.com/-qH5gM8_e5zA/Wq0OWghkjZI/AAAAAAAAImo/3gENq49UAPUaqw-ybuBoWEy2tlBNdeM6wCEwYBhgL/s400/19.png)](https://1.bp.blogspot.com/-qH5gM8_e5zA/Wq0OWghkjZI/AAAAAAAAImo/3gENq49UAPUaqw-ybuBoWEy2tlBNdeM6wCEwYBhgL/s1600/19.png)
[![](https://2.bp.blogspot.com/-dSlvDEn3NLw/Wq0OW9IOoBI/AAAAAAAAIms/uPwgRJ_nwzkB6qAltJkNWfcSZGUu6h44wCEwYBhgL/s400/20.png)](https://2.bp.blogspot.com/-dSlvDEn3NLw/Wq0OW9IOoBI/AAAAAAAAIms/uPwgRJ_nwzkB6qAltJkNWfcSZGUu6h44wCEwYBhgL/s1600/20.png)
讓我們再試試看剛剛的網址
[![](https://1.bp.blogspot.com/-Pm-1-hAQ2Xc/Wq0OXEQrCpI/AAAAAAAAImo/7jBfE4xT3w8Y4QRu_iDmqrxtYcEk-8AgACEwYBhgL/s400/21.png)](https://1.bp.blogspot.com/-Pm-1-hAQ2Xc/Wq0OXEQrCpI/AAAAAAAAImo/7jBfE4xT3w8Y4QRu_iDmqrxtYcEk-8AgACEwYBhgL/s1600/21.png)
這次不會壞掉了,且正確的導到HomeControllerContact Action去,接著試試不帶{Name}會怎麼樣
[![](https://2.bp.blogspot.com/-qulCDWyyTIs/Wq0OXeD8fFI/AAAAAAAAIms/3CVn_ntnPms8AvxipLFd34dYGInhrSN_wCEwYBhgL/s400/22.png)](https://2.bp.blogspot.com/-qulCDWyyTIs/Wq0OXeD8fFI/AAAAAAAAIms/3CVn_ntnPms8AvxipLFd34dYGInhrSN_wCEwYBhgL/s1600/22.png)
變成找不到資源,為什麼?因為我們的Name沒有設定為UrlParameter.Optional,所以是必帶的參數,這邊要特別注意!!! 之前教很多新人Route時很多人都卡在這邊
**Route**比對時必須完全符合才會被捕捉到
所以回頭審視我們的Route註冊目前有兩個規則
1. tellMe/whoAreYou/{name}
2\. {controller}/{action}/{id}
而我們帶的網址為 /tellMe/whoAreYou ,比對的規則將會是
由上到下,所以先比對了 1\. **tellMe/whoAreYou/{name}** 的規則 
tellMe,符合
whoAreYou,符合
Route要求要有Name,且不是Optional,所以必帶,”不符合”
這段Route會被跳過,執行比對2\. **{controller}/{action}/{id} **的規則
ControllertellMe,符合
ActionWhoAreYou,符合
Id為空值,因為為Optional,符合
所以實際程式去找的是TellMeController裡面的WhoAreYou這個Action,因為找不到這支程式所以顯示錯誤,而不是去執行規則1. HomeControllerContact這個Action
這是新手常常會犯的觀念錯誤,所以特別舉這個例子希望能夠較清楚的比較跟釐清,而Route因為還有很多種設定,避免一次太多造成混亂,所以先到這邊。試著將上述的觀念釐清,對於之後撰寫MVC Route時會很有幫助