ASP.NET MVC URL重寫與優化(初級篇)-使用Global路由表定制URL


引言---

  在現今搜索引擎制霸天下的時代,我們不得不做一些東西來討好爬蟲,進而提示網站的排名來博得一個看得過去的流量。

  URL重寫與優化就是搜索引擎優化的手段之一。

  假如某手機網站(基於ASP.NET MVC)分類頁面URL是這樣的,

  http://www.xxx.com/category/showcategory?categoryid=1000&view=list&orderby=price&page=1。

  太多的QueryString對爬蟲是不友好的,一般的做法是,去掉不必要的QueryString,讓URL更簡短 :http://www.xxx.com/category/1000。

  但一個好的URL要語義化,更好的反應網站結構,所以使用類名來作為URL要比分類id更勝一籌 :http://www.xxx.com/categoryname。

 

  這里列舉了URL重寫與優化的最為普遍的兩個需求,

  這里將分為兩篇來解決這兩個問題。

 

  這里我假設各位看官已經對ASP.NET MVC 已經有所了解。文中有任何問題歡迎指正。

  

 

一,認識Global路由表

 

  我們新建一個ASP.NET MVC Web程序的時候,會生成一個Global.asax文件。如下:

 

View Code
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using System.Web.Routing;
 7 
 8 namespace JohnConnor.Web
 9 {
10     // 注意: 有關啟用 IIS6 或 IIS7 經典模式的說明,
11     // 請訪問 http://go.microsoft.com/?LinkId=9394801
12 
13     public class MvcApplication : System.Web.HttpApplication
14     {
15         public static void RegisterGlobalFilters(GlobalFilterCollection filters)
16         {
17             filters.Add(new HandleErrorAttribute());
18         }
19 
20         public static void RegisterRoutes(RouteCollection routes)
21         {
22             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
23 
24             routes.MapRoute(
25                 "Default", // 路由名稱
26                 "{controller}/{action}/{id}", // 帶有參數的 URL
27                 new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值
28             );
29 
30         }
31 
32         protected void Application_Start()
33         {
34             AreaRegistration.RegisterAllAreas();
35 
36             RegisterGlobalFilters(GlobalFilters.Filters);
37             RegisterRoutes(RouteTable.Routes);
38         }
39     }
40 }

  首先Application_Start()是Web應用程序啟動的時候的入口。<RegisterGlobalFilters()方法是用來注冊全局篩選器的,與本篇內容關系不大>

  而RegisterRoutes()方法是用來注冊路由表的

  這里已經有了兩條默認的路由規則:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

  IgnoreRoute()是RouteCollection路由表類的擴展方法,用於忽略指定的路由請求。這句意思是忽略對擴展名為.axd文件的請求。<這個方法不在此詳述>

 

   我們主要來看這一條路由規則:

 

 routes.MapRoute(
                "Default", // 路由名稱
                "{controller}/{action}/{id}", // 帶有參數的 URL
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值
            );

 

  MapRoute()方法是一個添加路由映射的方法(RouteCollection類的擴展方法)。這里是它最常用的一個重載,映射指定的 URL 路由並設置默認路由值:

 

  • "Default"是路由的名稱,這個名稱在應用程序的路由的集合(routes對象)中是唯一的,如果重名生成時就會報錯。
  • "{controller}/{action}/{id}"代表的是路由的 URL表達式
  •  new { controller = "Home", action = "Index", id = UrlParameter.Optional } 聲明了一個包含路由值的object匿名對象

   

  這條語句添加了一條路由規則,將URL表達式映射到一個路由值-指向某個Controller下的某個Action方法。

  e.g.:我們在瀏覽器中輸入相對地址/home/index HomeController.Index()方法就會被調用。

 

  發布網站的時候Global.asax文件會被編譯成DLL。程序啟動的時候就會首先調用Application_Start()方法, 

  執行RegisterRoutes(RouteTable.Routes)語句后,路由表就完成注冊了,默認路由規則開始生效。

  有了這條默認規則,我們就可以使用/controllername/actionname?querystring=...這樣的相對URL來調用程序中的每個action方法。

  熟悉ASP.NET MVC的人可以想到,如果沒有什么特殊要求的系統,比如網站后台,就不用再折騰了,一條默認路由規則足矣撐起整個Web程序了。

 

 

二,路由匹配規則

 

  1.首先我們需要科普一下如何來定義一條URL表達式。

  首先URL表達式都是相對的,不包括主機域名部份(比如http://www.xxx.com)。{}保存的是占位符,“/”,“.”則用來作為分隔符,什么都有沒則是靜態內容:

  • URL /category/showcategory/1000  匹配 "{controller}/{action}/{id}"
  • URL /product/2012/4/28.html         匹配  “/product/{year}/{month}/{day}.html”  ,諸如此類。

 

  這里需要注意的是{controller}{action}是保留的兩個占位符,分別代表對應的控制器名稱和操作名稱。

  {controller}對應控制器的名稱,這里規定是控制器全名去掉Controller后綴的部份,CategoryController即Category

  {action}對應控制器內的Action方法的名稱。

 

  2.路由有兩種不同的操作。

 

  獲取路由值,當你在瀏覽器輸入一個URL時,程序會在我們添加的路由表中通過對比URL表達式進行匹配,找到對應路由值。

    我們來看一個例子,我們來添加兩條路由規則。

routes.MapRoute("Test", "where-are-you-going", new { controller = "Home", action = "Index" });
routes.MapRoute("Test1", "where-are-you-going", new { controller = "Home", action = "Others" });

  假設HomeController里有兩個Action 分別是Index()Others()

 

  各位看官覺得在瀏覽器輸入http://www.xxx.com/where-are-you-going 哪個方法會被調用呢?如果上下顛倒一下呢?

  <調用HomeController.Index()/顛倒后調用HomeController.Others>

 

  獲取URL,下面這段代碼就使用Url.Action方法通過Controller和Action名完全限定了一個URL,

  即我們有了一個路由值,通過在路由表中匹配,可以找到對應的URL模式,進而生成一個URL

<a href="@Url.Action("Index", "Home")">主頁</a>

  現在我們在默認的路由規則下再添加一條如下的路由規則

routes.MapRoute("MyHome", "myhome/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

  你覺得頁面會顯示什么呢?

<a href="http://www.xxx.com/">主頁</a>
or
<a href="http://www.xxx.com/myhome">主頁</a>

 

   如果把這條路由規則寫在默認規則的上面呢?

   <誰寫在上面就顯示其匹配的URL>

 

 

  3.上面的問題大家可以自己嘗試一下,很明顯,路由的匹配是 自上而下 的,只要匹配到第一條記錄,就會返回對應URL或者路由值。

  這一點非常重要。很多人在定制路由規則的時候,總是發現自己的規則不生效。那么你就應該檢查是不是被前面的路由覆蓋掉了。

 

三,解決開始的問題

 

  從這個站的URL可以看出,

  http://www.xxx.com/category/showcategory?categoryid=1000&view=list&orderby=price&page=1,

  用的應該只是默認路由規則,

  可以推斷出有一個名為Category的控制器,其中有個方法名為ShowCategory,必選參數為categoryid,其他為可選參數。

  根據上面介紹的Global路由表來完成URL重寫的知識,

  按照站長的要求,我們只需要添加一條路由規則就完事了。是不是很簡單?

 

routes.MapRoute("Category", "category/{categoryid}", new { controller = "Category", action = "ShowCategory" }

  

  這時候一定要注意喔,不要寫在默認路由的下面,你懂得。不然你就悲劇了。

 

  一般情況下我們建議如果你需要使用Globel文件來定制路由,請刪除最初的默認路由,並給每一個Action定制自己的路由。

routes.MapRoute("Home", "", new { controller = "Home", action = "Index" });

  使用上述路由來取代默認路由。

  瀏覽器輸入相對URL “/”時就會調用HomeController.Index()方法了。

  這樣做的原因是,默認路由容易與定制路由起沖突。

 

  強烈建議大家自己動手玩一玩Global文件,重寫URL來親身感受一下。其實有一個懸念我留給大家了,

  為什么默認規則下獲取首頁的URL是“/”而不是“/home/index”呢。^_^

  匹配規則還有貪婪匹配和缺省匹配一說,這個留大家去了解把。

 

 

  使用Global還是有很多的局限性的,上例中因為方法ShowCategory有一個參數categoryid,它存在與路由信息的鍵值對中,

  在配置時我們就可以使用占位符來{categoryid}來顯示它。

  換作http://www.xxx.com/categoryname 這樣的URL,如果不修改程序,Global是無能為力的,因為categoryname並不存在與路由信息的鍵值對中。

  應對這樣的較為復雜多變的URL重寫與優化的需求(需求總是復雜多變的=。=)。

 

  ---------------------------------------初級篇完--------------------------------------------

 

  進階篇中會教大家如何通過繼承RouteBase類來完全Hold住場面。祝大家五一快樂。回來再寫。。。

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM