2009年10月12日 星期一

ASP.NET 4.0中的URL Routing

在今年TechDays 2009的ASP.NET 4.0場次中,我介紹了一些ASP.NET 4.0的新功能,其中有許多功能都是在 3.5 SP1中展露頭角,可能在MVC中,也可能在Dynamic Data中,這些3.5 SP1中的功能在釋出後深受開發人員的好評,很多開發人員反映是否可以加入在Web Form中,因此MS也就從善如流的照辦了,其中一個功能就是 URL Routing機制。

過去URL Routing機制僅被MVC和Dynamic Data支援,如今ASP.NET 4.0當中直接納入了Routing類別,也就是說,WebForm也直接支援了Url Routing機制。

URL Routing機制可以讓我們很輕易的建立出REST風格(請參考REST一下吧)的網址,也可以讓我們輕易建構出類似Dynamic Data風格的網址,像是:
http://myWebSite/Product/Edit/XBOX
我們可以用上面的網址來表達要編輯一筆產品資料,產品名稱為XBOX。這樣的網址呈現方式不只更加的直覺清楚,同時也有著相當大的延展性,例如,我們可以用底下的網址表明要編輯名稱為Student資料表中的David同學的資料:
http://myWebSite/Edit/Student/David
當然,也可以用底下這個網址來表達要編輯名稱為Employ資料表中的Eric員工的資料:
http://myWebSite/Edit/Employ/Eric
而這兩個網頁理論上行為上完全一致,其實可以用同一個.aspx頁面來執行。

也就是說,傳統的WebForm .aspx頁面,在編輯不同的資料表時,幾乎註定要寫不同的頁面(來維護多個資料表),如果有三五個資料表要維護,這不是問題,反正透過Wizard很快就可以建立出這些.aspx頁面,但是,如果是一千兩千個資料表,那你就要好好思考了...

為何傳統的WebForm不能用『一個』.aspx頁面來處理這一兩千個資料表呢? 其實每個資料表的編輯行為(Behaivor)不是都一樣嗎?

是的,但是這背後的原因很多,主要是因為SqlDataSource、FormView、GridView的行為和DataBinding機制,造成了ASP.NET注定讓UI層和DB的相依性過高(在.aspx頁面中有SQL指令或是DataForm/DataGrid的template中有資料表欄位名稱),導致很難(不是絕對不行)設計出一個.aspx頁面來同時處理數個資料表的編輯動作。反過來說,如果想要這樣做,肯定就無法輕易的用FormView或是GridView來完成,而需要在.aspx頁面上動態地產生資料表欄位所對應的UI欄位,不過很慶幸,這我們已經在ASP.NET 3.5 Sp1中透過Dynamic Data技術實現了。現在我們透過DynamicData技術,已經可以動態的針對資料表來產生前端UI所需要的Control,也就是說,我們可以輕易設計出以一個.aspx頁面就處理多個資料表的功能了...(這背後涉及的技術很多,以後有機會我們慢慢談...)

既然在技術上已經可以實現,那URL也要稍加配合吧?所以,ASP.NET Dynamic Data Web Site/MVC開始支援URL Routing機制,過去我們的網址都是:
http://WebSite/Folder/PageA.aspx?Para1=abc&Para2=123
這樣的網址看起來真的很遜,當使用者看到上面這樣的網址時,會發現整個網址的設計其實是反映出應用程式開發的『資料夾』架構,這有幾個缺點:

1.安全性降低:因為使用者很容易知道我們把哪一個功能(頁面)放在哪一個目錄下。
2.網址無法表現出功能性:上面的網址只會呈現出資料夾,而非使用者在意的功能,這些資料夾規畫對於使用者來說沒有意義。

如果我們可以把它改成:
http://WebSite/FeatureName/ActionName/Parameter
這樣的網址,則網址就較有意義了,同時也符合我們架構大型(或超大型)ASP.NET應用程式的需求,因為我們可以事先規劃功能,然後將不同的功能切割為不同的網址表示法,這樣不管網站是由幾個人同時開發,都不會搞出亂七八糟的Folder和網站架構。而對於開發人員來說,也不需要管另一個開發人員到底把功能架在哪一個Folder的哪個.aspx頁面,在網頁和網頁需要溝通或是彼此呼叫的時候,只需要依照最初的SD規劃,redirect到某一個url(例如需要編輯產品AK47的資料時可以redirect到http://WebSite/Edit/Table/Products/AK47),而這個網址自然會被URL Routing機制導成真正的.aspx頁面,這對於開發大型網站也頗有助益。


OK,了解其意義之後,接著看ASP.NET 4.0怎麼架構Url Routing機制,其實很簡單,只需要在Global.asax中撰寫程式碼設定即可:

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Routing.RouteTable.Routes.Add("test1", _
New Routing.Route("Search/{ProductName}", _
New Routing.PageRouteHandler("~/WebForm1.aspx")))
End Sub
我們透過Routing這個新加入的類別,將『http://WebSite/Search/{產品名稱}』這樣的網址對應到WebForm1.aspx,如此一來,當使用者在網址列上輸入(或程式設計師透過redirect將網址導入『http://WebSite/Search/AK47』時,就會執行導http://WebSite/WebForm1.aspx

而開發人員可以在WebForm1.aspx中透過RouteData.Values("ProductName")抓取到參數值『AK47』,這樣就可以輕易實現URL Routing功能了。

7 則留言:

小沈 提到...

老師:
想請問一下,在內部網路中,使用silverlight,使用者的網頁必須下載安裝run-time才能順利運作,但是問題在於因為網域中的使用者並沒有安裝的權限,造成無法下載安裝,這樣子的問題微軟有好的解決方案嗎?也沒有SMS可供派送,如果利用WSUS可以讓使用者在更新時就安裝嗎?因為線在在導入的過程中發生了這樣的問題,只好來請教老師了,感謝老師!!

康廷數位文教網 提到...

當初就是因為 google 的 blogspot url 實在太漂亮了,才選擇在 google 落腳,對於有這方面潔癖的人來說,這真是個好功能啊。

GDX 提到...

您好,我想請問一下我加入了System.Web.Routing參考
可是我的System.Web.Routing裡面卻沒有PageRouteHandler這個類別
我的Framework是3.5 SP1
是否需要4.0才會支援?

GDX 提到...

補充一下
其他相關的類別都是有的(像是Route, RouteTable)

David 提到...

某些功能是4.0中才有的,特別是WebForm中支援URL Routing的部分。在3.5中URL Routing是針對MVC和Dynamic Web Site中使用的。

好手天生 提到...

請問站長:
我照您的方式做了asp.net 4.0 url routing了,但是在vs2010上測試OK,但在IIS7.x上都不OK捏,請問我是否哪裡沒弄好呢?

Lee 提到...

請問一下,用了Route改變url後css或javascript要如何取得正確的檔案路徑
href="Css/uploadify.css"

例如上面的連結會找不到該檔案
有點苦惱