雖然已經使用一段時間的 ASP.NET MVC,但畢竟之前使用 ASP.NET WebForm技術寫的程式多到數不清,無法拋棄,但仍然想要使用 MVC 的 Routing 啊。
經由 ASP.NET MVC 的激勵,在 ASP.NET 4.0 WebForm,特地加上了一組新的 Routing 的API,以支援愈來愈多的 SEO 需求。
單一網頁的 Routing
最簡單的Routing,就是簡單地把一個 Url 對應到一個 WebForm 的 aspx。以下就先簡單地建立一個 WebForm Application。
- 建立一個 Web Application,並指定名稱寫 TestRoutes
- 在 Global.asax.cs 中,修改 Application_Start 如下
void Application_Start(object sender, EventArgs e)
{
System.Web.Routing.RouteTable.Routes.MapPageRoute("about", "About", "~/About.aspx");
}
測試一下網頁,http://localhost:1295/About.aspx 與 http://localhost:1295/About 的結果是相同的。
這樣,我們就簡單地將某一 Request 對應到單一的網頁。
單一參數改成 Routing
建立舊有的網頁
我們先新增一個舊 Style 的 WebForm 網頁 Tag.aspx,並指定 Master Page 如下。
網頁的內容如下
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Tag.aspx.cs" Inherits="TestRoutes.Tag" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
指定 Tag 為
<asp:Label Text="text" runat="server" ID="_Tag" />
</asp:Content>
而 CodeBehind 程式如下
using System;
namespace TestRoutes
{
public partial class Tag : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
_Tag.Text = Request["Tag"];
}
}
}
測試一下網頁並加上參數 ?Tag=MVC,結果如預期地顯示如下
以上是最簡單不過的 WebForm 程式。現在呢,我想要讓 Url 可以讓搜尋引擎更方便地來搜尋(SEO),故想讓 Url 可以可使用 /Tags/MVC 來達到相同的效果。
改成 Routing 型式
第一步,仍然是在 Global.asax.cs 的 Application_Start 上修改 RouteTable,如下
void Application_Start(object sender, EventArgs e)
{
System.Web.Routing.RouteTable.Routes.MapPageRoute("about", "About", "~/About.aspx");
System.Web.Routing.RouteTable.Routes.MapPageRoute("tag", "Tags/{Tag}", "~/Tag.aspx");
}
接下來,修改 Tag.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
//_Tag.Text = Request["Tag"];
string routeValue = (string)Page.RouteData.Values["Tag"];
_Tag.Text = routeValue;
}
測試一下網頁 http://localhost:1295/Tags/MVC 果然和之前的結果是一樣的。
兩者兼顧
回過頭來測試一下,什麼? http://localhost:1295/Tag.aspx?tag=MVC 反而不能 work? 這非常讓客戶不能接受。我們希望即使SEO 化後,原來的 WebForm 存取方式也能正常。故改 code behind 如下。
protected void Page_Load(object sender, EventArgs e)
{
_Tag.Text = TagValue;
}
private string TagValue
{
get
{
string fromQuery = Request["Tag"];
if (string.IsNullOrEmpty(fromQuery))
{
string routeValue = (string)Page.RouteData.Values["Tag"];
return routeValue;
}
else
return fromQuery;
}
}
經過這次修改後,兩者都可以正常運作了。缺點呢?一看就知道,為了取得使用者要求的 Tag,並且能適用兩種Url 存取方式,必須大動土木地修改 Global.asax.cs 與每個網頁,實在很不人道,而且程式變的更難維護了。之後有空再來解決這一個問題。
使用 RouteValue expression builders
如果在每一頁的 aspx都需要在 code behind 上使用 Page.RouteData來讀取 route value,也太浪費時間了。因此 ASP.NET 4 介紹了一個新的 RouteValue expression builders 來顯示。範例如下
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Tag.aspx.cs" Inherits="TestRoutes.Tag" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
指定 Tag 為
<asp:Label Text="text" runat="server" ID="_Tag" />
<br />
使用 RouteValue expression builders方式,得到指定 Tag 為
<asp:Label runat="server" Text="<%$ RouteValue:Tag %>" />
</asp:Content>
簡單地使用 <%$ RouteValue:routeKey%> 語法,就可以讀取 RouteData 了。
製作 RESTFul的連結
要寫出 RESTFul 的連結其實很簡單,只是需要遵循以下RouteValue expression的規則
<%$RouteUrl:RouteName=yourRouteName,yourRouteKey=yourRoutKeyValue%>
其中yourRoutName 及 yourRouteKey 是在 Global.asax.cs 中註冊的 RouteTable,yourRouteKeyValue 即是要查詢的值。
舉例來說,若要在首頁(default.aspx)增加一個連結,可以使用如下的設定
<asp:HyperLink NavigateUrl="<%$RouteUrl:RouteName=tag,Tag=MVC %>" runat="server" Text="MVC" />
結論
在 WebForm 中使用這些 Routing 雖然不是難事,但與 MVC 相比起來,相對來說還是較難使用。在 ASP.NET MVC 中,使用 Html Helper 的 ActionLink 是非常直覺的事啊!而 WebForm 卻要記這個RouteValue expression。
範例下載