ASP.NET的路由系統(tǒng):根據(jù)路由規(guī)則生成URL
前面我們已經(jīng)提到過,ASP.NET 的路由系統(tǒng)主要具有兩個方面的應(yīng)用,其一就是通過注冊URL模板與物理文件路徑的匹配實(shí)現(xiàn)請求地址和物理地址的分離;另一個則是通過注冊的路由規(guī)測生成一個相應(yīng)的URL。后者通過調(diào)用RouteCollection類型的GetVirtualPath方法來實(shí)現(xiàn)。[源代碼從這里下載]
如下面的代碼片斷所示,GetVirtualPath定義了兩個GetVirtualPath方法重載,它們共同的參數(shù)requestContext和values分別表示請求上下文(RouteData和HTTP上下文的封裝)和用于替換定義在URL模板中的變量站位符的值。另一個GetVirtualPath方法具有一個額外的字符串參數(shù)name,它表示集合中具體使用的路由對象的注冊名稱(調(diào)用MapPageRoute方法時指定的第一個參數(shù))。而AppendTrailingSlash和LowercaseUrls決定在對生成的URL進(jìn)行規(guī)范化的時候是否添加一個“/”字符(如果沒有),以及是否需要將URL轉(zhuǎn)化為小寫。
1: public class RouteCollection : Collection<RouteBase>
2: {
3: //其他成員
4: public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
5: public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values);
6:
7: public bool AppendTrailingSlash { get; set; }
8: public bool LowercaseUrls { get; set; }
9: }
如果調(diào)用GetVirtualPath方法時沒有指定具體采用的路由對象,會遍歷整個集合的每個路由對象并調(diào)用其GetVirtualPath方法,如果返回的VirtualPathData不會Null則直接將其作為返回值;否則(找不到匹配的路由對象)返回Null。如果在調(diào)用GetVirtualPath確定了具體使用的路由對象,則直接調(diào)用該路由對象的GetVirtualPath方法并返回其執(zhí)行結(jié)果。
我們在調(diào)用GetVirtualPath方法的時候可以傳入Null作為第一個參數(shù)(requestContext),在這種情況下會基于當(dāng)前HTTP上下文(對應(yīng)于HttpContext的靜態(tài)屬性Current)創(chuàng)建一個RequestContext對象作為調(diào)用路由對象GetVirtualPath方法的同名參數(shù),該參數(shù)包含一個空的RouteData對象。如果當(dāng)前HTTP上下文不存在則直接拋出一個InvalidOperationException異常。
路由對象針對GetVirtualPath方法而進(jìn)行的路由匹配只要求URL模板中定義的變量的值都能被提供,而這些變量值具有三種來源,分別是路由對象定義的默認(rèn)變量值、指定RequestContext的RouteData提供的變量值(Values屬性)和手工提供的變量值(通過values參數(shù)指定的RouteValueDictionary對象),這三種變量值的選擇優(yōu)先級由低到高。同樣以之前定義關(guān)于獲取天氣信息的URL模板為例,下面是路由注冊代碼。
1: public class Global : System.Web.HttpApplication
2: {
3: protected void Application_Start(object sender, EventArgs e)
4: {
5: var defaults = new RouteValueDictionary { { "areacode", "010" }, { "days", 2 }};
6: var constaints = new RouteValueDictionary { { "areacode", @"0\d{2,3}" }, { "days", @"[1-3]{1}" } };
7: var dataTokens = new RouteValueDictionary { { "defaultCity", "BeiJing" }, { "defaultDays", 2 } };
8: RouteTable.Routes.MapPageRoute("default", "{areacode}/{days}", "~/weather.aspx", false, defaults, constaints, dataTokens);
9: }
10: }
我們在Weather.aspx頁面的后臺代碼中通過如果如下的代碼調(diào)用RouteTable和Routes熟悉的GetVirtualPath方法生成三個具體的URL。
1: public partial class Weather : Page
2: {
3: protected void Page_Load(object sender, EventArgs e)
4: {
5: RouteData routeData = new RouteData();
6: routeData.Values.Add("areaCode","0512");
7: routeData.Values.Add("days","1");
8: RequestContext requestContext = new RequestContext();
9: requestContext.HttpContext = new HttpContextWrapper(HttpContext.Current);
10: requestContext.RouteData = routeData;
11:
12: RouteValueDictionary values = new RouteValueDictionary();
13: values.Add("areaCode", "028");
14: values.Add("days", "3");
15:
16: Response.Write(RouteTable.Routes.GetVirtualPath(null,null).VirtualPath + "<br/>");
17: Response.Write(RouteTable.Routes.GetVirtualPath(requestContext, null).VirtualPath + "<br/>");
18: Response.Write(RouteTable.Routes.GetVirtualPath(requestContext, values).VirtualPath + "<br/>");
19: }
20: }
從上面的代碼片斷我們可以看到:第一次調(diào)用GetVirtualPath方法傳輸?shù)膔equestContext和values參數(shù)均為Null;第二次則指定了一個手工創(chuàng)建的RequestContext對象,其RouteData的Values屬性具有兩個變量(areaCode=0512;days=1),而values參數(shù)依然為Null;第三次我們同時為參數(shù)requestContext和values指定了具體的對象,而后者包含兩個參數(shù)(areaCode=028;days=3)。在瀏覽器上訪問Weather.aspx頁面會得到如下圖所示的3個URL。這充分證實(shí)了上面提到的關(guān)于變量選擇優(yōu)先級的結(jié)論。
ASP.NET的路由系統(tǒng):URL與物理文件的分離
ASP.NET的路由系統(tǒng):路由映射
ASP.NET的路由系統(tǒng):根據(jù)路由規(guī)則生成URL


前面我們已經(jīng)提到過,ASP.NET 的路由系統(tǒng)主要具有兩個方面的應(yīng)用,其一就是通過注冊URL模板與物理文件路徑的匹配實(shí)現(xiàn)請求地址和物理地址的分離;另一個則是通過注冊的路由規(guī)測生成一個相應(yīng)的URL。后者通過調(diào)用RouteCollection類型的GetVirtualPath方法來實(shí)現(xiàn)。[源代碼從這里下載]

浙公網(wǎng)安備 33010602011771號