概述

使用MVC Routing可以不必将URL映射到网站中特定文件。通过添加Routing规则,使URL能够安装指定的规则发送HTTP请求,这种方式能够简洁、方便、有效、快速的实现对指定页面的访问或者参数的传递,更易于被用户理解该URL。

MVC Routing之优

在不使用路由的 ASP.NET 应用程序中,对 URL 的传入请求通常映射到处理该请求的物理文件,如 .aspx 文件。 例如,对 http://server/application/Products.aspx?id=4 的请求映射到名为 Products.aspx 的文件,该文件包含代码和标记用于呈现对浏览器的响应。 网页使用查询字符串值 id=4 来确定要显示的内容类型。

在 ASP.NET 路由中,可以定义 URL 模式,这些模式映射到请求处理程序文件但是不必在 URL 中包含这些文件的名称。 另外,可以在 URL 模式中包含占位符,以便无需查询字符串,即可将变量数据传递到请求处理程序。

例如,在请求 http://server/application/Products/show/beverages 时,路由分析器可以将值 Products、show 和 beverages 传递给页处理程序。 在此示例中,如果路由是使用 URL 模式 server/application/{area}/{action}/{category} 定义的,则页处理程序将收到一个字典集合,在该集合中,与键 area 关联的值为 Products,键 action 的值为 show,键 category 的值为 beverages。 在不由 URL 路由管理的请求中,/Products/show/beverages 片断将被解释为应用程序中一个文件的路径。

关于Routing的详细介绍请移步

我要学ASP.NET MVC 3.0(三): 初识MVC Url映射潜规则Routing

URL 如何与路由匹配

路由在处理 URL 请求时,还尝试将请求的 URL 与路由匹配。 将 URL 请求与路由匹配取决于以下所有条件:

  • 包括在项目类型中的已经定义的路由模式或默认路由模式(如果有的话)。

  • 将路由添加到 Routes 集合中的顺序。

  • 已经提供给路由的所有默认值。

  • 已经提供给路由的任意约束。

  • 是否定义路由来处理匹配物理文件的请求。

为避免错误的处理程序处理请求,必须在定义路由时考虑以上所有条件。 出现在 Routes 集合中的 Route 对象的顺序是很重要的。 路由将在集合的整个路由过程中一直尝试匹配。 当匹配发生时,无法计算更多的路由。 通常,按从路由定义的具体性递减的顺序将路由添加到 Routes 属性。

实例说明

假定您使用以下模式添加路由:

  • 路由 1 设置为 {controller}/{action}/{id}

  • 路由 2 设置为 products/show/{id}

路由 2 将不再处理请求,这是因为首先计算路由 1,路由 1 始终匹配同样适用于路由 2 的请求。 对 http://server/application/products/show/bikes 的请求似乎能更好地匹配路由 2,但它是由路由 1 使用下列值处理的:

  • controller 为 products。

  • action 为 show。

  • id 为 bikes。

如果请求缺少参数,则会使用默认值。 因此,可能导致路由匹配意外的请求。 例如,假定您使用以下模式添加路由:

  • 路由 1:{report}/{year}/{month},对于 year 和 month 使用默认值。

  • 路由 2:{report}/{year},对于 year 使用默认值。

路由 2 将永远不处理请求。 路由 1 可能用于月度报表,而路由 2 可能用于年度报表。 但是,路由 1 中的默认值意味着将匹配同时适用于路由 2 的所有请求。

可以通过在模式中包括例如 annual/{report}/{year} 和
monthly/{report}/{year}/{month} 的常量来避免二义性。

如果 URL 与在 RouteTable 集合中定义的任何 Route 对象都不匹配,ASP.NET 路由将不处理请求。 相反,会将处理传递给 ASP.NET 页、Web 服务或其他 ASP.NET 终结点。

向MVC程序中添加路由

如果你想通过创建派生自 ControllerBase 类的类,并赋予它们以“Controller”结尾的名称来采纳实现控制器的 MVC 实例,此时您就不需要在 MVC 应用程序中再手动添加路由规则。 因为MVC程序已经预先配置了默认的路由规则,该规则将调用您在Controller类中实现的操作方法。

如果您想要在 MVC 应用程序中添加自定义路由,则要使用 MapRoute(RouteCollection, String, String) 方法,不要使用 MapPageRoute(String, String, String) 方法。

RouteCollectionExtensions.MapRoute 方法 (RouteCollection, String, String)

映射指定的 URL 路由。参数(应用程序的路由的集合,要映射的路由的名称,路由的 URL 模式)返回类型为System.Web.Routing.Route对映射路由的引用

 

RouteCollection.MapPageRoute 方法 (String, String, String)

提供用于定义 Web 窗体应用程序的路由的方法。参数(路由的名称,

路由的 URL 模式,路由的物理 URL)

提供此方法是为了方便编码。它等效于调用 Add 方法,然后传递使用 PageRouteHandler 类创建的 Route 对象。

下面的示例演示在 Global.asax 文件(该文件是在 MVC 应用程序的 Visual Studio 项目模板中定义的)中创建默认 MVC 路由的代码。

        public static void RegisterRoutes(RouteCollection routes)         {             //忽略对.axd文件的Route,也就是和WebForm一样直接去访问.axd文件             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 ); }
protected void Application_Start() { //在程序启动的时候注册我们前面定义的Route规则 RegisterRoutes(RouteTable.Routes); } }

设置URL参数默认值

定义路由时可以为参数分配一个默认值。 如果 URL 没有包括该参数的值,则会使用默认值。 通过将字典对象分配给 Route 类的 Defaults 属性,可以设置路由的默认值。 下面的示例演示如何使用 MapPageRoute(String, String, String, Boolean, RouteValueDictionary) 方法添加具有默认值的路由。

如下:MVC 应用程序的 Visual Studio 项目模板中默认 MVC 路由的代码

        public static void RegisterRoutes(RouteCollection routes)         {             //忽略对.axd文件的Route,也就是和WebForm一样直接去访问.axd文件             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 ); }
protected void Application_Start() { //在程序启动的时候注册我们前面定义的Route规则 RegisterRoutes(RouteTable.Routes); } }

RouteCollection.MapPageRoute 方法 (String, String, String, Boolean, RouteValueDictionary)

提供用于定义 Web 窗体应用程序的路由的方法。参数(路由的名称,路由的 URL 模式,路由的物理 URL,一个值 该值指示 ASP.NET 是否应验证用户是否有权访问物理 URL(始终会检查路由 URL),路由参数的默认值)

返回类型为System.Web.Routing.Route将添加到路由集合的路由

自定义默认路由

如下代码:

        public static void RegisterRoutes(RouteCollection routes)         {             //忽略对.axd文件的Route,也就是和WebForm一样直接去访问.axd文件             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapPageRoute("", "Category/{action}/{categoryName}", "~/categoriespage.aspx", true, new RouteValueDictionary {{"categoryName", "food"}, {"action", "show"}});
}

运行上面示例中演示的路由定义(使用针对 categoryName 的 food 的默认值和针对 action 的 show 的默认值)得到下表列出的结果。

 

URL

参数值

/Category

action = "show"(默认值) categoryName = "food"(默认值)

/Category/add

action = "add" categoryName = "food"(默认值)

/Category/add/beverages

action = "add" categoryName= "beverages"

对于 MVC 应用程序,通过 RouteCollectionExtensions.MapRoute 方法的重载(例如 MapRoute(RouteCollection, String, String, Object, Object))可以指定默认值。

在 URL 模式中处理可变数量的段

有时我们需要处理包含可变数量的 URL 段的 URL 请求。 定义路由时,可以指定 URL 是否具有比模式中更多的段,是否将额外的段视为最后一个段的一部分。 若要以此方式处理额外的段,可以用星号 (*) 标记最后一个参数。 该参数称为“可用于放置各种信息的”参数。 具有全部捕捉参数的路由也将与那些不包含最后一个参数的任意值的 URL 相匹配。 下面的示例演示一个与未知数量的段匹配的路由模式。

query/{queryname}/{*queryvalues}

ASP.NET 路由处理 URL 请求时,在示例中演示的路由定义得到下表列出的结果。

URL

参数值

/query/select/bikes/onsale

queryname = "select" queryvalues = "bikes/onsale"

/query/select/bikes

queryname = "select" queryvalues = "bikes"

/query/select

queryname = "select" queryvalues = Empty string

添加路由约束

除了按照 URL 中的参数数量将 URL 请求匹配到路由定义中,还可以指定参数中的值满足特定约束。 如果一个 URL 包含路由的约束以外的值,则该路由不用于处理请求。 添加约束以确保 URL 参数包含将在应用程序中起作用的值。

约束是通过使用正则表达式或使用实现 IRouteConstraint 接口的对象来定义的。 将路由定义添加到 Routes 集合时,同时也通过创建一个包含验证测试的 RouteValueDictionary 对象添加了约束。 字典中的关键字标识约束适用的参数。 字典中的值可以是表示正则表达式的字符串,也可以是实现 IRouteConstraint 接口的对象。

提供字符串后,路由将视字符串为正则表达式,并通过调用 Regex 类的 IsMatch 方法检查参数值是否有效。 总是将正则表达式视为不区分大小写。

提供 IRouteConstraint 对象后,ASP.NET 路由将通过调用 IRouteConstraint 对象的 Match 方法检查参数值是否有效。 Match 方法返回一个布尔值,该值指示参数值是否有效。

通过使用正则表达式可以规定参数格式,比如controller参数只能为4位数字:

new { controller = @"\d{4}"}

通过第IRouteConstraint 接口目前可以限制请求的类型.因为System.Web.Routing中提供了HttpMethodConstraint类, 这个类实现了IRouteConstraint 接口. 我们可以通过为RouteValueDictionary字典对象添加键为"httpMethod", 值为一个HttpMethodConstraint对象来为路由规则添加HTTP 谓词的限制, 比如限制一条路由规则只能处理GET请求:

httpMethod =  new HttpMethodConstraint(  "GET", "POST"  )

完整的代码如下:

            routes.MapRoute(                 "Default",                                              // 路由名称                 "{controller}/{action}/{id}",                           // 带有参数的URL                 new { controller = "Home", action = "Index", id = "" },  //参数默认值                 new { controller = @"\d{4}" , httpMethod = new HttpMethodConstraint( "GET", "POST" ) }             );

当然我们也可以在外部先创建一个RouteValueDictionary对象在作为MapRoute的参数传入, 这只是语法问题.

示例:演示如何使用 MapPageRoute 方法创建具有约束的路由,该约束限制可在 localeyear 参数中包括的值。 (在 MVC 应用程序中,使用 MapRoute 方法。)

        public static void RegisterRoutes(RouteCollection routes)         {             routes.MapPageRoute("",                                 "Category/{action}/{categoryName}",                                 "~/categoriespage.aspx",                                 true,                                 new RouteValueDictionary {{"categoryName", "food"}, {"action", "show"}},                                 new RouteValueDictionary {{"locale", "[a-z]{2}-[a-z]{2}"}, {"year", @"\d{4}"}}                 );
}

路由处理 URL 请求时,在上一示例中演示的路由定义生成下表列出的结果。

 

URL

结果

/US

无匹配。 localeyear 都是必需的。

/US/08

无匹配。 对 year 的约束需要 4 个数字。

/US/2008

locale = "US" year = "2008"

 
 
实例:下面是自定义的一些路由规则
        public static void RegisterRoutes(RouteCollection routes)         {             //忽略对.axd文件的Route,也就是和WebForm一样直接去访问.axd文件             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// URL匹配 // Details/list/CQ/100,200-3 routes.MapRoute( "Details", "Details/{action}/{city}/{price}-{star}", new {controller = "Details", action = "list", city = "CQ", price = "-1,-1", star = "-1"}, new {city = @"[a-zA-Z]*", price = @"(\d)+\,(\d)+", star = "[-1-5]"} );
// URL匹配 // Details/所有匹配 routes.MapRoute( "Details", "Details/{*values}", new { controller = "Details", action = "default", id = "" } );
// URL匹配 // Home/. routes.MapRoute( "Home", "{*values}", new { controller = "Home", action = "index" } ); }
 
 
没有路由怎么办?
 

在某些情况下,即使为网站启用了请求,ASP.NET 路由也不处理请求。 本节介绍路由不处理请求的一些情况。

找到匹配 URL 模式的物理文件

默认情况下,路由不处理映射到 Web 服务器上现有物理文件的请求。 例如,如果 Products/Beverages/Coffee.aspx 上存在物理文件,则路由不处理对 http://server/application/Products/Beverages/Coffee.aspx 的请求。 即使匹配一个定义的模式(例如 {controller}/{action}/{id}),路由也不处理该请求。

如果希望路由处理所有请求(包括指向文件的请求),可以通过将 RouteCollection 对象的 RouteExistingFiles 属性设置为 true 来重写默认行为。 将该值设置为 true 后,与定义的模式匹配的所有请求都将由路由处理。

为 URL 模式显式禁用路由

还可以指定路由不应处理某些 URL 请求。 通过定义路由并指定应使用 StopRoutingHandler 类来处理该模式,来阻止路由处理某些特定请求。 当 StopRoutingHandler 对象处理请求时,StopRoutingHandler 对象会阻止以任何其他方式将该请求处理为路由。 而是会将该请求处理为 ASP.NET 页、Web 服务或其他 ASP.NET 终结点。 可以使用 RouteCollection.Ignore 方法(对于 MVC 应用程序,为 RouteCollectionExtensions.IgnoreRoute)创建使用 StopRoutingHandler 类的路由。 下面的示例演示如何阻止路由处理 WebResource.axd 文件的请求。

            //忽略对.axd文件的Route,也就是和WebForm一样直接去访问.axd文件             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

mvc路由问题的更多相关文章

  1. ASP.NET MVC 路由(一)

    ASP.NET MVC路由(一) 前言 从这一章开始,我们即将进入MVC的世界,在学习MVC的过程中在网上搜索了一下,资料还是蛮多的,只不过对于我这样的初学者来看还是有点难度,自己就想看到有一篇引导性 ...

  2. ASP.NET MVC 路由(二)

     ASP.NET MVC路由(二) 前言 在上一篇中,提及了Route.RouteCollection对象的一些信息,以及它们的结构所对应的关系.按照处理流程走下来还有遗留的疑问没有解决这个篇幅就来讲 ...

  3. ASP.NET MVC 路由(三)

    ASP.NET MVC路由(三) 前言 通过前两篇的学习会对路由系统会有一个初步的了解,并且对路由系统中的Url规则有个简单的了解,在大家的脑海中也有个印象了,那么路由系统在ASP.NETMVC中所处 ...

  4. ASP.NET MVC 路由(四)

    ASP.NET MVC路由(四) 前言 在前面的篇幅中我们讲解路由系统在MVC中的运行过程以及粗略的原理,想必看过前面篇幅的朋友应该对路由有个概念性的了解了,本篇来讲解区域,在读完本篇后不会肯定的让你 ...

  5. ASP.NET MVC 路由(五)

    ASP.NET MVC 路由(五) 前言 前面的篇幅讲解了MVC中的路由系统,只是大概的一个实现流程,让大家更清晰路由系统在MVC中所做的以及所在的位置,通过模糊的概念描述.思维导图没法让您看到路由的 ...

  6. MVC路由探寻,涉及路由的惯例、自定义片段变量、约束、生成链接和URL等

    引子 在了解MVC路由之前,必须了解的概念是"片段".片段是指除主机名和查询字符串以外的.以"/"分隔的各个部分.比如,在http://site.com/Hom ...

  7. Asp.Net MVC 路由 - Asp.Net 编程 - 张子阳

    http://cache.baiducontent.com/c?m=9d78d513d98316fa03acd2294d01d6165909c7256b96c4523f8a9c12d522195646 ...

  8. ASP.NET MVC 路由进阶(之二)--自定义路由约束

    3.自定义路由约束 什么叫自定义路由约束呢?假如路由格式为archive/{year}/{month}/{day},其中year,month,day是有约束条件的,必须是数字,而且有一定范围. 这时候 ...

  9. 自定义MVC路由配置

    首先我用MVC4新增一个订单查看的功能 1.创建控制器OrderController namespace MvcApplication3.Controllers { public class Orde ...

  10. AngularJS html5Mode与ASP.NET MVC路由

    AngularJS html5Mode与ASP.NET MVC路由共存 前言 很久之前便听说AngularJS,非常酷,最近也比较火,我也在持续关注这个技术,只是没有认真投入学习.前不久公司找我们部门 ...

随机推荐

  1. Android Service的分类详解

    按照启动方式分类 谷歌官网对Service的分类 Service根据启动方式分为两类:Started和Bound.其中,Started()是通过startService()来启动,主要用于程序内部使用 ...

  2. BZOJ4487 JSOI2015染色问题(组合数学+容斥原理)

    逐个去除限制.第四个限制显然可以容斥,即染恰好c种颜色的方案数=染至多c种颜色的方案数-染至多c-1种颜色的方案数+染至多c-2种颜色的方案数…… 然后是限制二.同样可以容斥,即恰好选n行的方案数=至 ...

  3. Hyperledger Fabric架构详解

    区块链开源实现HYPERLEDGER FABRIC架构详解 区块链开源实现HYPERLEDGER FABRIC架构详解 2018年5月26日 陶辉 Comments 10 Comments hyper ...

  4. fastjson对json操作

    fastjson对json字符串JSONObject和JSONArray互相转换操作示例  fastjson的方法: Fastjson API入口类是com.alibaba.fastjson.JSON ...

  5. a 标签中 title 属性样式修改

    无文字描述,直接上测试页,看效果. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  6. Java拷贝构造函数初尝试

    浅复制(浅克隆) :被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. 深复制(深克隆) :被复制 ...

  7. Cannot read property 'resetFields' of undefined 问题及引申

    问题描述: 使用element开发我的后台系统,编辑和新增使用了同一个弹出框<el-dialog><el-form></el-form></el-dialog ...

  8. Restful 接口权限控制

    前言 有人说,每个人都是平等的: 也有人说,人生来就是不平等的: 在人类社会中,并没有绝对的公平, 一件事,并不是所有人都能去做: 一样物,并不是所有人都能够拥有. 每个人都有自己的角色,每种角色都有 ...

  9. MDIO/MDC(SMI)接口-leonwang202

    ChinaUnix博客 http://blog.chinaunix.net/uid-24148050-id-132863.html

  10. poj 1528 Perfection

    题目链接:http://poj.org/problem?id=1528 题目大意:输入一个数n,然后求出约数的和sum,在与这一个数n进行比较,如果sum>n,则输出ABUNDANT,如果sum ...