[C#][.Net MVC] 03. MVC下的URL Route 設定
說到MVC網站就不能不提到Route設定!
什麼是Route? 在現實生活中比較接近於郵差與地圖的關係,你將想要送的東西交給郵差,郵差依據包裹上的地址,透過地圖找到目的地然後投遞。
而對應到程式中[網址]就是你包裹要送達的目的地址,Route就是[地圖],而網址的[參數]就是你要投遞的包裹。
接著我們來看看專案內的Route在哪邊設定,又它是如何透過網址知道該把[包裹]送去哪支程式的,這邊先把我們之前的專案執行起來,並且點擊[關於]
可以看到關於頁的網址為 /Home/About
接著我們在HomeController的About下中斷點後再點擊一次網頁的[關於]按鈕,會發現程式停在我們下中斷點的地方了? 為什麼知道程式會跑到這邊呢 ?
這一切都是因為有Route指路的關係
RouteConfig
Route的規則是可以自己制訂的,而制定的地方就在App_Start資料夾底下的RouteConfig裡面
讓我們來解讀這段程式碼,首先routes.MapRoute就是註冊地址的方法,裡面有幾個參數分別為
Name : 你對於這個Route的命名
Url : 網址條件,當網址符合這個條件特徵時,就會依據這個Route的指示去找對應執行的程式碼
defaults : 參數的預設值
相信光是講解參數的意義對於要理解Route還有相當的距離,讓我們直接來實戰理解 /Home/About這串網址如何對應到Route的吧,剛剛有說, routes.MapRoute的Url參數是用來判斷網址特徵是否相符,如果相符就會被這串Route捕捉到,但是這兩個怎麼看都不像啊!
真實網址 : /Home/About
Route Url : {controller}/{action}/{id}
首先必須先知道一件事情,當Route Url的網址用{ }包起來的時候,代表他是個變數,什麼是變數?
變數是一個表示值,它可以是任意的值,而{}裡面的字就是變數的名稱,以上述例子為例
我們有一個變數叫做controller,它可以是任意的值
我們有一個變數叫做action,它可以是任意得值
我們有一個變數叫做id,它也可以是任意的值
那套入/Home/About會變成什麼結果?
我們有一個變數叫做controller,它現在的值是Home
我們有一個變數叫做action,它現在的值是About
我們有一個變數叫做id,它現在沒有值
而Route的制定中,controller跟action為保留字,意思是告訴他要執行哪個controller跟Action,依據這邊的規定,所以它知道要去執行Home這個Controller,裡面一個叫做About的Action。
[編按: 在Controller裡面寫的方法我們稱之為Action,而他通常都會回傳ActionResult]
再讓我們看一個例子 : [首頁]
首頁的網址為 : http://localhost:54004/
https://www.google.com.tw/search?q=facebook
而www.google.com.tw就是Domain,當讀到這串Domain時,就會透DNS找到Google的伺服器,然後呼叫它,並且請求他執行/search?q=facebook,這也是為什麼我們討論Route時沒有把Domain納進來,Domain只是讓網路能找到你服務的伺服器位置,後面才是你撰寫程式要處理的Route網址
所以首頁網址等於
首頁網址 : /
Route Url : {controller}/{action}/{id}
我們有一個變數叫做controller,它現在沒有值
我們有一個變數叫做action,它現在沒有值
我們有一個變數叫做id,它現在沒有值
什麼都沒有,那程式到底要執行哪邊? 這時候Default終於派上用場了,Default的意思就是,當沒有值
時,請用我設定的值代替吧
所以
controller為空值,所以用Default的值代替,所以它的值為Home
action為空值,所以用Default的值代替,所以它的值為Index
id為空值,但Default設定它為UrlParameter.Optional,意思是它是選擇性的,如果沒有沒關係。
所以這個Route設定又完美符合了,所以依據條件,我們去HomeController的Index下中斷點,試試看進入首頁時是不是會停在這邊
的確,他依據規則跑到了HomeController的Index Action了。
那舉一反三一下,換句話說首頁網址也可以是 /Home/Index 摟,試試看,你會發現它的確走到一樣的中斷點
你可能會說,那這樣Route還有什麼好學的,這個寫法幾乎萬用了啊? 的確在MVC預設專案中的這個Route設定我們通常稱它為萬用Route,但也因為它幾乎萬用,所以不好管理,所以正常來說都還是會制定自己的Route規則,好方便管理,這個之後慢慢寫專案碰到多了會更有感觸。
接著我們來試著修改一下程式,讓我們的{id}能派上用場吧!!
在剛剛的案例中,因為id設定是Optional所以都沒派上用場,來試試看他怎麼用吧,首先我們先在 HomeController 的 About Action中加入參數 id,並且把回傳的訊息改成 Your id is (你帶進來的值)
接著我們重新執行一次程式,並且把網址改成/Home/About/Steven
再練習一次Route比對
我們有一個變數叫做controller,它現在的值是Home
我們有一個變數叫做action,它現在的值是About
我們有一個變數叫做id,它現在的值是Steven
讓接著看中斷點,把滑鼠移到id那的參數會看到,Id依據我們下的網址,以Steven帶進來了
接著看網頁呈現的成果
練習制定一個屬於我們的Route
看了兩個範例,我們也來制定一個Route規則給自己用吧,而且我們不要用變數的方式。
我們希望有個網址為/tellMe/whoAreYou/{name},且name跟之前的id一樣是個變數,可以由你自己打
喜歡的文字來決定,寫完後來試試看這個route可不可行
結果竟然錯了,來看看少了什麼
網址 : /tellMe/whoAreYou/steven
Route Url : /tellMe/whoAreYou/{name}
比對tellMe,符合
比對whoAreYou,符合
比對Name這個變數,現在的值為Steve
然後呢? 有沒有發現即便這邊都比對正確,符合route規則,但我們沒告訴他Controller是誰,Action是
誰,程式當然不知道該去執行誰,所以再來改一下,因為我們還沒學到如何建立Controller跟Action,
所以先用現成的, 導到homeController的Contact吧!
讓我們再試試看剛剛的網址
這次不會壞掉了,且正確的導到HomeController的Contact Action去,接著試試不帶{Name}會怎麼樣
變成找不到資源,為什麼?因為我們的Name沒有設定 UrlParameter.Optional,所以是必帶的參數,這邊要特別注意!!! 之前教很多新人Route時很多人都卡在這邊
Route比對時必須完全符合才會被捕捉到
所以回頭審視我們的Route註冊目前有兩個規則
- tellMe/whoAreYou/{name}
- {controller}/{action}/{id}
而我們帶的網址為 /tellMe/whoAreYou ,比對的規則將會是
由上到下,所以先比對了 1. tellMe/whoAreYou/{name} 的規則
tellMe,符合
whoAreYou,符合
Route要求要有Name,且不是Optional,所以必帶,不符合
這段Route會被跳過,執行比對2. {controller}/{action}/{id}的規則
Controller為tellMe,符合
Action為WhoAreYou,符合
Id為空值,因為為Optional,符合
所以實際程式去找的是TellMeController裡面的WhoAreYou這個Action,因為找不到這支程式所以顯示錯誤,而不是去執行規則1. 的 HomeController 的Contact這個Action。
這是新手常常會犯的觀念錯誤,所以特別舉這個例子希望能夠較清楚的比較跟釐清,而Route因為還有很多種設定,避免一次太多造成混亂,所以先到這邊。試著將上述的觀念釐清,對於之後撰寫MVCRoute時會很有幫助
最後,如果你喜歡我們的文章,別忘了到我們的FB粉絲團按讚喔!!