在mvc中路由的配置,直接關系着我們的請求訪問的控制器和方法;url對seo有着重要作用,全靠mvc內部定義的配置路由和生成url的方法在有的時間是不夠的,本文就來了解一下自定義配置路由和url的生成。
一、RouteBase類簡介
在新建一個mvc項目后,打開global文件,可以看到路由的注冊是使用一個RouteCollection類型的參數來實現的。按F12轉到定義會發現,其繼承了Collection<RouteBase>,除了一些MapRoute等一些方法之外還有一個Add方法,其簽名為:
public void Add(string name, RouteBase item);
實際上就是一個標記路由的名字,還有一個是RouteBase類,按F12,其對應的有兩個方法:
//當在派生類中重寫時,會返回有關請求的路由信息。 public abstract RouteData GetRouteData(HttpContextBase httpContext); //當在派生類中重寫時,會檢查路由是否與指定值匹配,如果匹配,則生成一個 URL,然后檢索有關該路由的信息 public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
第一個方法:通過處理請求信息httpContext,來指定通過哪個控制器和方法處理請求的;第二個方法用來指定請求頁的連接生成的URL.下面就通過一個實例來說明以上兩個方法的使用。
二、使用RouteBase的方法
2.1需求說明
為了讓url更加一目了然,在列表分頁時,我們通過使用如下URL:http://www.***.com/分類/List/Page/n,意思就是某個分類的第n頁列表。與此同時,我們對應的上一頁,下一頁生成對應的URL分別為http://www.***.com/分類/List/Page/n-1,http://www.***.com/分類/List/Page/n+1。下面以產品分類列表分頁為例,即http://localhost:***/Product/List/page/n。當然該需求應該有更好的解決方案,在此僅為了說明RouteBase的使用。為了演示,我們先新建一個MVC項目,在controllers文件夾添加一個ProductController,並簡單添加一個類表方法:
public ActionResult List(int page = 1) { ViewBag.count = page; ViewBag.content="第"+page+"頁"; return View(); }
並添加對應的視圖,
@{ ViewBag.Title = "List"; } <h2>產品列表</h2> <a href="@Url.Action("Product", "List", new { page = "page", id = Convert.ToInt32(ViewBag.count) - 1 })">上一頁</a> <a href="@Url.Action("Product","List",new {page="page",id= ViewBag.count})"> @ViewBag.content</a> <a href="@Url.Action("Product", "List", new { page = "page", id = Convert.ToInt32(ViewBag.count) + 1 })">下一頁</a>
然后添加一個文件夾Infranstructure,並新建一個類MyHelper,然后讓其繼承RouteBase類,如圖:
2.2GetRouteData的使用
為了配置路由,我們不使用MapRoute方法,可以把global文件里面的默認的MapRoute去掉,我們使用上面的GetRouteData方法,我們通過httpcontext來指定控制器里面的方法以到達處理請求的目的。代碼如下:
public class MyHelper : RouteBase { public override RouteData GetRouteData(HttpContextBase httpContext) { //指定處理請求的路由對象為MvcRouteHandler對象 var data = new RouteData(this, new MvcRouteHandler()); //接受請求的url,並對其指定controller和action以及action的參數 string strUrl = httpContext.Request.RawUrl; string[] arry = strUrl.Split('/'); if (arry.Length > 4) { data.Values.Add("controller", "Product"); data.Values.Add("action", "List"); data.Values.Add(arry[3], arry[4]); return data; } /*如果不符合要求的url,返回null,以便使用其他路由匹配,進而指定 controller和action以及action的參數*/ return null; } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { //我們暫且返回一個null
return null; }
}
因為開始的時間,我們去掉了MapRoute,現在我們要使用Add方法,所以在global文件中添加
routes.Add(new MyHelper());
現在運行程序,並在地址欄輸入http://localhost:3519/Product/List/Page/1,效果圖如下:
此時的請求已經通過我們的自定義路由生效,但是我們發現,上一頁和下一頁的連接不是我們想要的,如果想達到我們的要求,那么我們就需要使用GetVirtualPath方法,對該請求頁的連接生成指定的URL。
2.3 GetVirtualPath的使用
廢話不多說,還是把代碼貼出來,部分說明見注釋:
/// <summary> /// 為指定請求頁生成特定的url的樣子 /// </summary> /// <param name="requestContext">請求頁</param> /// <param name="values">請求頁中的Html.Action等輔助類</param> /// <returns></returns> public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { //先判斷請求是否符合要求——請求的action為List,page不能為空。 if (requestContext.RouteData.Values["action"].ToString()=="List"&& !string.IsNullOrEmpty(requestContext.RouteData.Values["page"].ToString())) { //定義一個Url字符串 string strUrl = string.Empty; //如果values中有四個值,做下面的操作 if (values.Count == 4) { if (Convert.ToInt32(values["id"]) >= 1) { strUrl = values["controller"].ToString() + "/" + values["action"].ToString() + "/" + values["page"].ToString() + "/" + values["id"].ToString(); } else { strUrl = values["controller"].ToString() + "/" + values["action"].ToString() + "/" + values["page"].ToString() + "/1#"; } return new VirtualPathData(this, strUrl); } } return null; }
現在運行http://localhost:3519/Product/List/Page/1頁面,已經是我們想要的結果了。
注意:上面的兩個方法判斷的時間一定要精確的判斷,否則可能指定到錯誤的控制器和方法上以及錯誤的url。再者,當不符合指定要求時要返回到null,以便使用其他的路由配置。
三、總結
本文主要通過一個分頁的實例來說明自定義路由和URL的生成。例子或許欠佳,但是比較好理解。源碼.