ASP.NET 路由

.NET Framework 4
 

更新:2007 年 11 月

ASP.NET 路由使您可以使用不必映射到网站中特定文件的 URL。由于 URL 不必映射到文件,所以可以在 Web 应用程序中使用 URL,这些 URL 是描述性的用户操作,因此更易于被用户理解。

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

在 ASP.NET 路由中,您可以定义 URL 模式,该模式包含在处理 URL 请求时使用的值的占位符。在运行时,应用程序名称后面的 URL 部分根据您所定义的 URL 模式分析为离散值。例如,在请求 http://server/application/Products/show/beverages 时,路由分析器可以将值 Products、show 和 beverages 传递给请求的处理程序。相反,在一个不由 URL 路由管理的请求中,/Products/show/beverages 片断将被解释为应用程序中一个文件的路径。

还可以使用 URL 模式通过编程方式来创建对应于路由的 URL。这使您能够集中逻辑用于创建 ASP.NET 应用程序中的超链接。

ASP.NET 路由不同于其他 URL 重写方案。URL 重写通过在将请求发送到网页之前实际更改 URL 来处理传入请求。例如,一个使用 URL 重写的应用程序可能会将 URL 从 /Products/Widgets/ 更改为 /Products.aspx?id=4。此外,URL 重写通常没有相应的 API 来创建基于模式的 URL。在 URL 重写中,如果更改了 URL 模式,则必须手动更新包含原始 URL 的所有超链接。

由于 ASP.NET 路由可以从 URL 提取值,所以处理传入请求时不更改 URL。如果必须创建一个 URL,则将参数值传递到为您生成 URL 的方法中。若要更改 URL 模式,请在某位置更改该模式,您在应用程序中创建的基于该模式的所有链接将自动使用新模式。

定义的 URL 模式称作“路由”。在路由中,您可以指定占位符,用于映射到从 URL 请求中分析的值。您还可以指定用于匹配 URL 请求的常量值。

在路由中,您可以通过用大括号( { 和 })括住占位符来定义占位符(称为“URL 参数”)。分析 URL 时将 / 字符解释为分隔符。将路由定义中不是分隔符和不在大括号中的信息视为一个常量值。将从两个分隔符之间提取的值分配给占位符。

您可以在分隔符之间定义多个占位符,但必须用一个常量值分隔开。例如,{language}-{country}/{action} 是有效的路由模式。但是,由于占位符之间没有常量或分隔符,所以 {language}{country}/{action} 不是有效的模式。因此,路由无法确定在哪里将language 占位符的值与 country 占位符的值分隔开。

下表演示有效的路由模式和一些与模式匹配的 URL 请求的示例。

 

路由定义

匹配 URL 示例

{controller}/{action}/{id}

/Products/show/beverages

{table}/Details.aspx

/Products/Details.aspx

blog/{action}/{entry}

/blog/show/123

{reporttype}/{year}/{month}/{day}

/sales/2008/1/5

{locale}/{action}

/zh-cn/show

{language}-{country}/{action}

/zh-cn/show

通常情况下,您在 Global.asax 文件中 Application_Start 事件的处理程序调用的方法中添加路由。该方法可确保应用程序启动时路由可用。还使您能够在对应用程序进行单元测试时直接调用方法。如果您想在对应用程序进行单元测试时直接调用一个注册路由的方法,则该方法必须是静态的(Visual Basic 中的 Shared),并且必须具有一个 RouteCollection 参数。

您可以通过将路由添加到 RouteTable 类的静态 Routes 属性来添加路由。Routes 属性是一个 RouteCollection 对象,存储 ASP.NET 应用程序的所有路由。下面的示例演示从 Global.asax 文件中添加一个 Route 对象的代码,该对象定义了名为 action 和categoryName 的两个 URL 参数。

 
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
} public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route
(
"Category/{action}/{categoryName}"
, new CategoryRouteHandler()
));
}

定义路由时可以为参数分配一个默认值。如果 URL 没有包括该参数的值,则会使用默认值。通过将字典分配给 Route 类的 Defaults属性,可以设置路由的默认值。下面的示例演示一个包含默认值的路由。

 
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
} public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route
(
"Category/{action}/{categoryName}"
new CategoryRouteHandler()
)
{
Defaults = new RouteValueDictionary
{{"categoryName", "food"}, {"action", "show"}}
}
);
}

ASP.NET 路由处理 URL 请求时,在示例中演示的路由定义(使用针对 categoryName 的 food 的默认值和针对 action 的 show 的默认值)得到下表列出的结果。

 

URL

参数值

/Category

action = "show"(默认值)

categoryName = "food"(默认值)

/Category/add

action = "add"

categoryName = "food"(默认值)

/Category/add/beverages

action = "add"

categoryName= "beverages"

有时您需要处理包含可变数量的 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 对象添加了约束。然后将此对象分配给 Constraints 属性。字典中的关键字标识约束适用的参数。字典中的值可以是表示正则表达式的字符串,也可以是实现 IRouteConstraint 接口的对象。

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

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

下面的示例演示限制在 locale 和 year 参数中包含的值的约束。

 
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
} public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route
(
"{locale}/{year}"
, new ReportRouteHandler()
)
{
Constraints = new RouteValueDictionary
{{"locale", "[a-z]{2}-[a-z]{2}"},{year, @"\d{4}"}}
});
}

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

 

URL

结果

/zh-CN

无匹配。locale 和 year 都是必需的。

/zh-CN/08

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

/zh-CN/2008

locale = "zh-CN"

year = "2008"

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

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

还可以指定路由不应处理某些 URL 请求。通过定义路由并指定应使用 StopRoutingHandler 类来处理该模式,来阻止路由处理某些特定请求。当 StopRoutingHandler 对象处理请求时,StopRoutingHandler 对象会阻止以任何其他方式将该请求处理为路由。相反,会将该请求处理为 ASP.NET 页、Web 服务或其他 ASP.NET 终结点。例如,您可以添加以下路由定义来阻止路由处理 WebResource.axd 文件的请求。

 
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route("{resource}.axd/{*pathInfo}", new StopRouteHandler()));
}

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

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

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

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

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

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

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

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

  • 路由 1:{controller}/{action}/{id}

  • 路由 2:products/show/{id}

由于先计算路由 1,并将一直匹配也适用于路由 2 的请求,所以路由 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 终结点。

在希望集中逻辑用于构造 URL 时可以使用路由来生成 URL。通过将参数值作为字典传递给 RouteCollection 对象的 GetVirtualPath方法来创建 URL。GetVirtualPath 方法在 RouteCollection 对象中查找与字典中的参数匹配第一个路由。匹配路由用于生成 URL。下面的示例演示路由定义。

 
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route
(
"Category/{action}/{categoryName}"
new CategoryRouteHandler()
)
{
Defaults = new RouteValueDictionary {{"categoryName", "food"},
{"action", "show"}}
}
);
}

下面的示例演示一个基于路由创建 URL 的控件。

 
Dim urlParameters As RouteValueDictionary

urlParameters = New RouteValueDictionary(New With {.categoryName = "beverages", _
.action = "summarize"})
HyperLink1.NavigateUrl = RouteTable.Routes.GetVirtualPath _
(context, urlParameters).VirtualPath
 
HyperLink1.NavigateUrl = RouteTable.Routes.GetVirtualPath
(context,
new RouteValueDictionary {
{ "categoryName", "beverages" },
{"action", "summarize" }}
).VirtualPath;

运行此代码时,HyperLink1 控件将包含 NavigateUrl 属性中的值“Category/summarize/beverages”。

从路由创建 URL 时,可以通过包括路由的名称来指定使用哪个路由创建 URL。有关更多信息,请参见如何:通过路由构造 URL。

社区附加资源

添加

 
 

类型:.net;问题:ASP.NET路由;结果:ASP.NET 路由 .NET Framework 4的更多相关文章

  1. .NET/ASP.NET Routing路由(深入解析路由系统架构原理)

    阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模型的入口 4.ASP.NET Routing 路由对象模型的内部结构 4 ...

  2. .NET/ASP.NET Routing路由(深入解析路由系统架构原理)http://wangqingpei557.blog.51cto.com/1009349/1312422

    阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模型的入口 4.ASP.NET Routing 路由对象模型的内部结构 4 ...

  3. NET/ASP.NET Routing路由(深入解析路由系统架构原理)(转载)

    NET/ASP.NET Routing路由(深入解析路由系统架构原理) 阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模 ...

  4. 一、ASP.NET Routing路由(深入解析路由系统架构原理)

    阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模型的入口 4.ASP.NET Routing 路由对象模型的内部结构 4 ...

  5. 白话ASP.NET MVC之一:Url 路由

    好久没有写关于ASP.NET MVC的东西了,虽然<ASP.NET MVC4框架揭秘>已经完完整整的看完一遍,但是感觉和一锅粥差不多,没什么可写的,因为我自己不理解,也就写不出来.现在开始 ...

  6. ASP.NET MVC5高级编程 之 路由

    每个ASP.NET MVC应用程序都需要路由来定义自己处理请求的方式.路由是MVC应用程序的入口点.路由的核心工作是将一个请求映射到一个操作 路由主要有两种用途: 匹配传入的请求(该请求不匹配服务器文 ...

  7. 给Asp.Net MVC及WebApi添加路由优先级

    一.为什么需要路由优先级 大家都知道我们在Asp.Net MVC项目或WebApi项目中注册路由是没有优先级的,当项目比较大.或有多个区域.或多个Web项目.或采用插件式框架开发时,我们的路由注册很可 ...

  8. 【ASP.NET Web API教程】4.1 ASP.NET Web API中的路由

    原文:[ASP.NET Web API教程]4.1 ASP.NET Web API中的路由 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. ...

  9. Asp.Net MVC 进阶篇:路由匹配 实现博客路径 和文章路径

    Asp.Net MVC 进阶篇:路由匹配 实现博客路径 和文章路径 我们要实现 通过路由 匹配出 博客地址 和博客文章地址 例如下面的这两个地址 //http://www.cnblogs.com/ma ...

  10. asp.net core mvc 中间件之路由

    asp.net core mvc 中间件之路由 路由中间件 首先看路由中间件的源码 先用httpContext实例化一个路由上下文,然后把中间件接收到的路由添加到路由上下文的路由集合 然后把路由上下文 ...

随机推荐

  1. jquery下json数组的操作用法实例

    jquery下json数组的操作用法实例: jquery中操作JSON数组的情况中遍历方法用的比较多,但用添加移除这些好像就不是太多了. 试过json[i].remove(),json.remove( ...

  2. ansible实现发布、回滚功能

    ansible的两篇博客,本来是打算合二为一的,发现只用一篇写,嗯,好鬼长.... 一向秉承简单为美的我于是忍痛割爱,一分为二了 ansible实现升级发布.回滚功能 1.应用场景 在实际生产环境中, ...

  3. 双十字路口交通仿真程序(VS2010+MFC)

    这个程序是我上研二上学期时下一届师弟师妹们的面向对象课程大作业,当时我正好看过两三本 C++ 书籍,虽然忙着项目,但还是忙里偷闲检验了下自己.从设计到实现,耗时一周左右,完成于 2013 年年底. 虽 ...

  4. idea更换git地址操作

    更换地址: git remote set-url origin XXXXXXXXXXXXXXX 查看远程地址: git remote -v

  5. 08-THREE.JS 点面创建物体,克隆物体,多材质物体

    <!DOCTYPE html> <html> <head> <title></title> < <script src=&quo ...

  6. php mysql 查询

    抓取结果集对象中数据并且转换数组 $row = mysqli_fetch_assoc(结果集对象); 从结果集对象中抓取一行记录->转换关联数组 $row = mysqli_fetch_row( ...

  7. [基本操作] kd 树

    概念就不说了吧,网上教程满天飞 学了半天才知道,kd 树实质上只干了两件事情: 1.快速定位一个点 / 矩形 2.有理有据地优化暴力 第一点大概是可以来做二维平面上给点/矩形打标记的问题 第二点大概是 ...

  8. Qt之事件处理机制

    思维导读 一.事件简介 QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发.QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. 常见的QT事件类型如下: 键盘事件: 按键按下 ...

  9. C#异步编程(三)内核模式线程同步

    其实,在开发过程中,无论是用户模式的同步构造还是内核模式,都应该尽量避免.因为线程同步都会造成阻塞,这就影响了我们的并发量,也影响整个应用的效率.不过有些情况,我们不得不进行线程同步. 内核模式 wi ...

  10. python数据类型,int,str,bool

    一,python中的int() int在python中主要用来运算,对字符串的转化,用int(str)表示,并且需要str.isdigit为真. 在int()中二进制的转换如下: #bit_lengt ...