發(fā)文章
發(fā)文工具
撰寫
網(wǎng)文摘手
文檔
視頻
思維導圖
隨筆
相冊
原創(chuàng)同步助手
其他工具
圖片轉文字
文件清理
AI助手
留言交流
路由機制最顯著的一個效果就是實現(xiàn)URL和物理文件的分離。這個分離了之后有三個好處:更靈活,更好的可讀性,SEO更友好。
具體是這樣的:靈活在于文件的路徑有了更改(例如放到了一個新的文件夾里面),那就得把所有涉及到那個文件的URL都改一遍,懶一點的就Ctrl+H。如果用了路由映射的話,只需要在一個地方改就可以了,簡潔省事;更好的可讀在于傳統(tǒng)的URL在傳參的時候,都會在問號“?”后面都會以[參數(shù)名]=[參數(shù)值]的形式一個個的連接起來,就像這樣子
Http://127.0.0.1:8083/WebForm1.aspx?param1=parameterValue1¶m2=parameterValue2
但是在路由機制下的URL會變得比較簡潔明了
Http://127.0.0.1:8083/WebForm1/parameterValue1/parameterValue2(路由的模式暫不提);
SEO友好這點我無法舉例子了,呵呵!
下面則舉一個簡單的例子來演示如何利用這個路由機制來實現(xiàn)URL與物理文件的分離。
在MVC的項目的Global.asax文件中,路由的定義都放在了一RegisterRoutes(RouteCollection routes)的靜態(tài)方法里頭,這個方法在Application_Start()調用。而在ASP.NET里面也是類似,路由的定義都得在Application_Start()里面完成,代碼如下
protected void Application_Start(object sender, EventArgs e) { RouteValueDictionary defaultParam = new RouteValueDictionary { { "param1", "*" }, { "param2", "*" } }; RouteTable.Routes.MapPageRoute("default", "WebForm1/{param1}/{param2}", "~/WebForm1.aspx", true, defaultParam); }
這里主要添加路由的是調用MapPageRoute方法,里面的參數(shù)大致跟MVC下添加路由的類似,也是包含了路由的名稱,路由的模式,物理文件名等等,在這里我給兩個參數(shù)都定義了默認值,param1和param2都是“*”,其實也可以定義其他的約束,例如參數(shù)值要符合某種格式要求,至于MapPageRoute方法的其他重載,羅列如下
1 public Route MapPageRoute(string routeName, string routeUrl, string physicalFile); 2 public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess); 3 public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults); 4 public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints); 5 public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens);
在這個例子中需要一個位于根目錄下的aspx頁面,名為WebForm1.aspx,它的load事件綁定的方法如下
protected void Page_Load(object sender, EventArgs e) { StringBuilder sb = new StringBuilder(); string temp=this.RouteData.Values["param1"].ToString(); sb.AppendFormat("Param1:{0}<br/>", temp==""?"*":temp); temp = this.RouteData.Values["param2"].ToString(); sb.AppendFormat("Param2:{0}<br/>", temp == "" ? "*" : temp); Response.Write(sb.ToString()); }
生成之后,鍵入不同的URL效果如下
其實添加這個路由的不光只是通過MapPageRoute方法,這里還有另一種方式,通過實現(xiàn)IHttpHandler接口和IRouteHandler。還是從頭開始說說吧,RouteTable的Routes屬性實際上是一個RouteCollection類型的實例,由于它是一個集合類型的,可以通過調用它的Add方法來添加一個路由Route的實例。這個Route的實例就包括了URL的模式和一些處理規(guī)則(包括請求中對應哪個物理文件等等。)
涉及到的類的類圖如下
這里定義了兩個類,一個MyHttpHandler,實現(xiàn)IHttpHandler接口;另一個MyRouteHandler,實現(xiàn)IRouteHandler接口。Route的構造函數(shù)可傳入一個IRouteHandler的參數(shù),傳參時就用到自己定義的MyRouteHandler類。而這個IRouteHandler的成員里頭有個GetHttpHandler(RequestContext requestContext)方法,這個方法就是獲取一個實現(xiàn)IHttpHandler的類的實例,這里就返回就是自己定義的MyHttpHandler的實例。至于MyHttpHandler類里面,有一個virtual void ProcessRequest(HttpContext context)的虛方法,這個虛方法就是實際請求一個虛擬路徑上的處理程序。
這里粘一下代碼,主要是兩個類的定義
1 public class MyHttpHandler : IHttpHandler 2 { 3 4 public RequestContext RequestContext { get; private set; } 5 6 public MyHttpHandler(RequestContext context) 7 { 8 9 this.RequestContext = context; 10 11 } 12 13 #region IHttpHandler 成員 14 15 public virtual void ProcessRequest(HttpContext context) 16 { 17 //這里調用的文件的物理路徑,如果文件的路徑有改動的話,統(tǒng)一在這里改就可以了 18 context.Server.Execute("/" + RequestContext.RouteData.Values["page"]); 19 } 20 21 public bool IsReusable 22 { 23 24 get { return false; } 25 26 } 27 28 #endregion 29 30 } 31
1 public class MyRouteHandler : IRouteHandler 2 { 3 4 #region IRouteHandler 成員 5 6 public IHttpHandler GetHttpHandler(RequestContext requestContext) 7 { 8 9 return new MyHttpHandler(requestContext); 10 11 } 12 13 #endregion 14 15 }
在Application_Start(object sender, EventArgs e)里面只需添加一行代碼
RouteTable.Routes.Add(new Route("{param1}/{param2}/{page}", new MyRouteHandler()));
WebForm1.aspx的代碼不需要作任何更改,用http://localhost:1144/122343/abcdef/WebForm1.aspx發(fā)出請求,結果還是一樣
不過這里的參數(shù)不能為空了,以為沒有設默認值。
在前面羅列MapPageRoute方法的重載時也發(fā)現(xiàn),URL上面的參數(shù)可以給參數(shù)設定默認值,對參數(shù)的格式進行限制,下面則嘗試嘗試。無論是默認值還是格式約束,都要使用RouteValueDictionary這個類。
protected void Application_Start(object sender, EventArgs e) { RouteValueDictionary defaultParam = new RouteValueDictionary { { "param1", "0" }, { "param2", "0" } };//param1和param2的默認值都是0 RouteValueDictionary constraint = new RouteValueDictionary { { "param2", @"^\d+$" } };//param2要是一個正整數(shù) RouteTable.Routes.MapPageRoute("default", "WebForm1/{param1}/{param2}", "~/WebForm1.aspx", true, defaultParam, constraint); }
各個URL和結果如下列表所示
請求URL
結果
http://localhost:1144/WebForm1
Param1:0Param2:0
http://localhost:1144/WebForm1/sdfb
Param1:sdfbParam2:0
http://localhost:1144/WebForm1/sdfb/343
Param1:sdfbParam2:343
http://localhost:1144/WebForm1/sdfb/sfe
HTTP 404 錯誤 無法找到資源。
如果用IHttpHandler接口和IRouteHandler的話,則需要在Application_Start方法里面做一下改動
protected void Application_Start(object sender, EventArgs e) { RouteValueDictionary defaultParam = new RouteValueDictionary { { "param1", "0" }, { "param2", "0" } }; RouteValueDictionary constraint = new RouteValueDictionary { { "param2", @"^\d+$" } }; RouteTable.Routes.Add(new Route("{page}/{param1}/{param2}",defaultParam,constraint, new MyRouteHandler())); }
結果跟上面表格的一樣。
對于上面使用MapPageRoute方法的這種情況來說,如果按照上面的路由設置,那么如果按照之前文件路徑那樣去請求的話,照樣能訪問到指定的頁面。例如就上面一直使用的WebForm1.aspx,按照這個http://localhost:1144/WebForm1.aspx URL去請求的話,也能訪問到WebForm1.aspx,但是有差別的是我們的路由它不作任何處理,在路由里設置的默認值根本沒有生效,結果如下:
Param1:*
Param2:*
如果要讓這種URL也要路由的話,則需要設置一個屬性
RouteTable.Routes.RouteExistingFiles = true;
顧名思義,它表明了是否要對一個存在的文件進行路由。它其實是RouteCollection類的一個屬性,對于整個站點的路由來說,它是一個全局屬性,默認值為false。當把它設成ture之后,用回http://localhost:1144/WebForm1.aspx進行請求,得出的結果如下:
Param1:WebForm1.aspx
Param2:0
也就是說路由生效了,WebForm1.aspx被看作是參數(shù)1,而不是一個物理文件的文件名了,0則是參數(shù)2的默認值。
現(xiàn)在所有URL都會經(jīng)過路由處理,那么js,css,圖片等文件引用都會被路由。例如在頁面上添加這個
<img src="b6126b3468327b5c251f143c.jpg" width="300" height="500" />
結果只能是這樣
這時需要對部分文件取消路由,
RouteTable.Routes.Ignore("{filename}.jpg/{*pathInfo}");
圖片就可以出來了,吾王歸來
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
可是吾王又不見了,為啥????
這個路由機制還有另一個用途,就是根據(jù)路由來構造新的URL,這個構造主要是利用一個方法GetVirtualPath,這個方法RouteCollection有,Route也有。不同的是,調用RouteCollection的GetVirtualPath時,它會遍歷整個集合中所有Route對象,逐個對象去調用該Route對象自身的GetVirtualPath方法,直到返回值不為null為止,如果到最終都是null的,那只能返回null。
當我們定義這樣的路由
RouteValueDictionary defaultParam = new RouteValueDictionary { { "param1", "0" }, { "param2", "0" } }; RouteValueDictionary constraint = new RouteValueDictionary { { "param2", @"^\d+$" } }; RouteTable.Routes.MapPageRoute("default", "{param1}/{param2}", "~/WebForm1.aspx", true, defaultParam, constraint);
在WebForm1.aspx的與Load時間綁定的方法里面添加以下代碼
RouteData routeData = new RouteData(); routeData.Values.Add("param1", "abc"); routeData.Values.Add("param2", "123"); RouteValueDictionary values = new RouteValueDictionary(); values.Add("param1", "efg"); values.Add("param2", "456"); Response.Write(RouteTable.Routes.GetVirtualPath(null, null).VirtualPath + "<br/>"); Response.Write(RouteTable.Routes.GetVirtualPath(Request.RequestContext, null).VirtualPath + "<br/>"); Response.Write(RouteTable.Routes.GetVirtualPath(Request.RequestContext, values).VirtualPath + "<br/>");
當我們以http://localhost:1144/abc/123請求時,得出的三個URL分別是
/
/abc/123
/efg/456
從上面代碼看出,第一次調用時是沒有傳RequestContext,也沒有提供路由的參數(shù),得出的URL是“/”;第二次調用時只傳了當前的RequestContext,沒有提供路由參數(shù),得出的URL跟當前的一樣,是“/abc/123”;第三次RequestContext和路由參數(shù)都傳了,路由參數(shù)是param1是abc,param2是123,得出的URL是“/efg/456”。由此可見,當傳入了路由參數(shù)時,生成的URL肯定是按照路由參數(shù)生成的;當沒傳路由參數(shù)且只傳RequestContext時,生成的URL是按照RequestContext的路由參數(shù)來生成的;當什么也沒傳的時候,就只能生成所有參數(shù)為空的URL。即對于生成URL來說,路由參數(shù)比RequestContext優(yōu)先級更高。
其實這個構造URL的有什么作用我還不清楚,先記著留個印象,到后來萬一用上也可以留個底。
這篇文章吶其實在兩個月之前就起草了,由于各種原因擱置了下來,現(xiàn)在重新寫一下。曾經(jīng)想過寫一系列的有關APS.NET MVC的文章,可惜了解的少,能寫的更少。這篇文章里面不足的肯定很多,希望各位多多指點,謝謝!
最后附上一些比較有參考價值的文章
ASP.NET MVC路由擴展:路由映射
ASP.NET的路由系統(tǒng):URL與物理文件的分離
ASP.NET的路由系統(tǒng):根據(jù)路由規(guī)則生成URL
ASP.NET的路由系統(tǒng):路由映射
System.Web.Routing入門及進階 上篇
System.Web.Routing入門及進階 下篇
小弟這篇文章來源于上面羅列文章大部分內容,如果冒犯了的,小弟把這篇文章撤出園子首頁吧!
來自: 昵稱10504424 > 《工作》
0條評論
發(fā)表
請遵守用戶 評論公約
ASP.NET MVC Route之WebForm路由與源碼分析(一)
ASP.NET MVC Route之WebForm路由與源碼分析(一)WebForm中路由的淵源。public Route MapPageRoute(string routeName, string routeUrl,...
從零開始學習 ASP.NET MVC 1.0 (二) 識別URL的Routing組件
MapRoute( string name, string url, object defaults);public static Route MapRoute(this RouteCollection routes, string name, stri...
路由對象針對GetVirtualPath方法而進行的路由匹配只要求URL模板中定義的變量的值都能被提供,而這些變量值具有三種來源,分別是路由對象定義的默認變量值、指定RequestContext的RouteData提供的變量值...
白話學習MVC(四)URL路由
注意:如果是ASP.NET程序則是利用RouteCollection對象的PageMapRoute方法來進行注冊,在PageMapRoute方法中,將實例化一個Route對象并放入路由表中,當實例化Route對象時,其參數(shù)中會有一個RouteHandle...
僅此一文讓你明白ASP.NET MVC原理
ASP.NET MVC由以下兩個核心組成部分構成:一個名為UrlRoutingModule的自定義HttpModule,用來解析Controller與Action名稱;把RouteData...
URL Rewriting with ASP.NET
URL Rewriting with ASP.NET來自CodeProject:
學習 ASP.NET MVC (第一回)理論篇
學習 ASP.NET MVC (第一回)理論篇。URL Routing: ASP.NET MVC使用的是URL進行驅動的,根據(jù)程序中指定的規(guī)則從URL中確定Controller名,Action名,其他參數(shù)。獨立于ASP.NET MVC框架的組件,可用于任何A...
ASP.NET MVC 實現(xiàn)二級域名
自從微軟發(fā)布 ASP.NET MVC 和routing engine (System.Web.Routing)以來,就設法讓我們明白你完全能控制URL和routing,只要與你的application path相結合進行擴展,任何問題都迎刃而解。遺憾的是,ASP.N...
ASP.NET MVC Framework 系列
ASP.NET MVC Framework 系列序言。做為設計模式的王者,MVC在眾多領域都成為良好的模型的代名詞,從前在ASP.NET下我們只能依靠Monorail來實現(xiàn)ASP.NET下無控件的MVC,但是現(xiàn)在ASP.NET 下的MVC已經(jīng)成為現(xiàn)實...
微信掃碼,在手機上查看選中內容