在现今搜索引擎制霸天下的时代,我们不得不做一些东西来讨好爬虫,进而提示网站的排名来博得一个看得过去的流量。

  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文件。如下:

 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方法的名称。

【重写路由后缀时 需要在配置文件里加上 modules 标签 设置runAllManagedModulesForAllRequests属性为true】

<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true"/>
<handlers>

  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重写与优化的需求(需求总是复杂多变的=。=)。

最新文章

  1. Win10 IIS本地部署MVC网站时不能运行?
  2. HDU 4162 最小表示法
  3. 【HDOJ】1071 The area
  4. 性能调优之提高 ASP.NET Web 应用性能的 24 种方法和技巧
  5. jsel、tl是什么
  6. Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划
  7. 自定义函数hello,并注册到hive源码中并重新编译
  8. Hystrix入门与分析(二):依赖隔离之线程池隔离
  9. 当业务逻辑没错,直接mapper里面出错时
  10. Spark编译
  11. hdu1215-七夕节-(埃氏筛+唯一分解定理)
  12. python-状态模式
  13. Mysql批量导入约束报错
  14. MacBook下java环境的搭建
  15. oracle的JOB
  16. 如何使用Flashfxp上传下载文件
  17. copy_from_user分析
  18. Taylor series
  19. LeetCode 25 —— K 个一组翻转链表
  20. 天池历届大赛答辩PPT及视频

热门文章

  1. 《c# 实现p2p文件分享与传输系统》 二、 设计
  2. IoT:template
  3. layout属性
  4. ElementRef, @ViewChild &amp; Renderer
  5. openstack开发环境搭建
  6. pkg_resources----Entry Points为程序提供扩展点
  7. 【239】◀▶IEW-Unit04
  8. 错误:(26, 13) Failed to resolve: com.android.support:appcompat-v7:27.+
  9. Primer回顾 标准库类型
  10. strlen细节以及sizeof细节