ASP.NET路由[ASP.NET Routing]
ASP.NET路由[ASP.NET Routing]
ASP.NET路由允许你在使用URL时不必匹配到网站中具体的文件,因为这个URL不必匹配到一个文件,你使用了描述用户行为且更容易被用户理解的URL。
ASP.NET MVC框架和ASP.NET动态数据(Dynamic Data)扩展路由为MVC应用和动态数据应用增加了特色。
在不使用路由的ASP.NET应用中,一个新的请求会被映射到一个物理文件并由该文件处理这个请求,例如一个.aspx文件。例如,如下请求http://server/application/Products.aspx?id=4会题映射到一个包含代码和标签来向浏览器渲染响应的Products.aspx文件。Web页面人员使用id=4的查询字符来确定显示的内容。
使用ASP.NET路由,你可以定义映射请求-处理程序(request-handler)文件的URL模式,但没必要在将这些文件的名字包含在这个URL中。除此之外,你还可以通过在URL模式中使用占位符来向请求处理程序传输变量数据,而不必使用查询字符串。
例如,如下请求 http://server/application/Products/show/beverages,路由分析器会向页面处理器传入Products,show,beverages这些值。在这个例子中,如果使用server/application/{area}/{action}/{category}URL模式定义路由,页面处理器将会收到一个字典集合,这个集合中包含以下键值对,area:Products,action:show,category:beverages。如果是在一个不被URL路由管理的请求中,/Products/show/beverages片断将会被当作应用中的一个文件路径解释执行。
一、 路由[Routes]
路由是被处理程序映射的URL模式。处理程序可以是一个物理文件,例如Web Form应用中的.aspx文件。处理也可以是处理请求的类,例如MVC应用中的控制器。为了定义一个路由,你需要创建一个Route类的实例来指定URL模式,处理程序和可选的路由名称。
你需要给RouteTable类的Routes静态属性添加Route对象来为应用添加路由。Routes属性是一个RouteCollection对象,其中存放着应用中所有路由规则。
你通常没有必要为MVC应用编写代码添加来添加路由规则。Visual Studio的MVC项目模板包含了预配置的URL路由规则。他们定义在MvcApplication类,这个类在Global.asax文件中。
二、 URL模式[URL Patterns]
一个URL模式可以包含字面值(literal)和可变的占位符(参考URL参数)。这些字面值和占位符在URL片断中通过斜线(/)字符来分开和定位。
当一个请求到达,这个URL被解析成片断和占位符,这些变量会提供给请求处理器。这个过程和将数据通过查询字符串(query strings)中解析和传输至请求处理器很类似。这两种情况下变量信息都会包含在URL中并传到处理程序的键值对的表单中。对于查询字符串而言,所有键(keys)和值(values)都包含在URL中。对于路由方式,所有键就是在URL模式中定义的占位符名称,只有值包含中URL中。
在一个URL模式中,你定义的占位符被大括号包裹起来({and})。你可以在一个片断中定义多个占位符,但是它们必须被字面值分隔开。例如,{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} |
/US/show |
{language}-{country}/{action} |
/en-US/show |
MVC应用中标准的URL模式[Typical URL Patterns in MVC Applications]
在MVC应用中,路由标准的URL模式包含{controller}和 {action}占位符。
当接收到一个请求时,它先被发送到UrlRoutingModule对象,再发送到MvcHandler HTTP处理程序。MvcHandler HTTP处理程序确定需要执行的控制器,通过给URL中的controller值添加”Controller”后缀从而确定将处理本次请求的控制器类型名称。URL中的action值确定调用的处理方法。
例如,URL路径 /Products会被映射成ProductsController控制器。action参数的值是被调用的处理方法的名称。URL路径/Products/show的映射结果将会是调用类ProductsController 的方法Show。
下表给出了默认的URL模式和它们能处理的URL请求示例。
默认URL模式 |
匹配URL示例 |
{controller}/{action}/{id} |
http://server/application/Products/show/beverages |
{resource}.axd/{*pathInfo} |
http://server/application/WebResource.axd?d=... |
路由使用模式 {resource}.axd/{*pathInfo} 来阻止对网络文件的请求,例如WebReource.axd,ScriptResource.axd被传递给一个控制器。
对于IIS7.0,可以不用扩展名。对于IIS6.0,你必须将扩展名.mvc添加到URL模式,如下所示:{controller}.mvc/{action}/{id}
三、 为Web Forms应用程序添加路由[Add Routes to a Web Forms Application]
在Web Form应用中,你可以使用类RouteCollection的方法MapPageRoute(String, String, String) 创建路由。方法MapPageRoute创建Route对象并将其添加RouteCollection对象中。你需要为Route对象在参数在指定一些属性,用来传给方法MapPageRoute。
通常情况下,你在方法中添加的路由会被Global.asax文件中Application_Start 方法处理器调用。这种方法确保了这些路由在应用程序启动时可以正常调用。它也允许你在为应用程序做单元测试时可直接调用该方法。当你在做单元测试时如果想要直接调用一个方法,该方法在注册时就必须是静态(Visual Basic中Shared)且有一个RouteCollection参数。
下例中演示了Global.asax文件中添加一个Route对象,该对象定义了action和categoryName两个参数。URL中还定义了一个被定向到名为Categories.aspx的物理页面。
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
} public static void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("",
"Category/{action}/{categoryName}",
"~/categoriespage.aspx");
}
四、 为MVC应用程序添加路由[Adding Routes to an MVC Application]
在MVC应用程序中,如果你采用MVC实现控制器的约定,即派生自类ControllerBase且以“Controller”结尾命名,那么你根本不需要搬运添加路由。预配置的路由将会执行你实现的控制器类中的处理方法。
如果你希望在MVC应用程序中添加自定义的路由,你可以使用方法MapRoute(RouteCollection, String, String) 来取代方法MapPageRoute(String, String, String)。
下面示例中演示在Global.asax文件中创建默认MVC路由的代码,即是Visual Studio中MVC应用程序的项目模板。
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
); } protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
五、 为URL参数设置默认值[Setting Default Values for URL Parameters]
当你定义一个路由时,你可以为参数指定一个默认值。如果一个参数的值不在URL中,则使用默认值。给路由设置默认值时是给类Route的属性Defaults指定一个字典对象。下例演示了如何使用方法MapPageRoute(String, String, String, Boolean, RouteValueDictionary)添加一个包含默认值的路由。
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
} public static void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("",
"Category/{action}/{categoryName}",
"~/categoriespage.aspx",
true,
new RouteValueDictionary
{{"categoryName", "food"}, {"action", "show"}});
}
下图中演示了ASP.NET路由处理URL请求,路由定义(categoryName的默认值为food,action默认为show)和解析结果:
URL |
Parameter values |
/Category |
action = "show" (default value) categoryName = "food" (default value) |
/Category/add |
action = "add" categoryName = "food" (default value) |
/Category/add/beverages |
action = "add" categoryName= "beverages" |
对于MVC应用程序,方法RouteCollectionExtensions.MapRoute的重载版本,如MapRoute(RouteCollection, String, String, Object, Object),允许你指定默认值。
六、 URL模式中处理可变数量片断[Handling a Variable Number of Segments in a URL Pattern]
有时候你必须处理包含可变个数的URL片断的URL请求。当你定义一个路由时,你可以指定当一个URL拥有比模式中还要多的片断时,额外的片断会被当作最后一个片断对待。你需要为最后一个参数添加一个星号(*)来用这种方式处理额外的片断。这被称作全匹配(catch-all)参数。包含全匹配参数也将匹配最后参数不带任何值的URL。下例展示一个可以匹配无法确定片断长度的路由模式。
query/{queryname}/{*queryvalues}
下图中演示了ASP.NET路由处理URL请求,路由定义和解析结果。
URL |
Parameter values |
/query/select/bikes/onsale |
queryname = "select" queryvalues = "bikes/onsale" |
/query/select/bikes |
queryname = "select" queryvalues = "bikes" |
/query/select |
queryname = "select" queryvalues = Empty string |
七、 为路由添加约束[Adding Constraints to Routes]
路由模式中除了定义了可匹配URL请求的参数个数,还可以指定这些参数的值需要满足的某些约束。如果一个URL中的参数值不符合一个路由的约束,那么此路由不会处理该请求。你添加的约束条件是为了确保URL参数中包含的值能在你的应用程序中工作。
约束条件是用正则表达式或实现了接口IRouteConstraint的对象来定义。当你将一条路由添加进Routes 集合时,你可以添加包含验证测试的对象RouteValueDictionary约束条件。字典中的键唯一标识符合约束条件的参数。字典中的值既可以是符合正则表达式的字符串,也可以是实现接口IRouteConstraint的对象。
如果你提供一个字符串,路由会将它当作符合正则表达式的值,并调用Regex类的IsMatch()方法检查该参数值是否符合规则。正则表达式总是不区分大小写检查。
如果你提供了一个IRouteConstraint对象,ASP.NET路由调用IRouteConstraint对象的Match()方法来检查参数值是否合法。Match()方法返回布尔值来表明参数值是否合法。
下例中演示如何利用方法MapPageRoute 添加一条路由,并为参数locale和year添加约束。(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 |
Result |
/US |
No match. Both locale and year are required. |
/US/08 |
No match. The constraint on year requires 4 digits. |
/US/2008 |
locale = "US" year = "2008" |
八、 路由不起作用的情况[Scenarios When Routing Is Not Applied]
在某些情况下,ASP.NET路由即使可用也不会处理请求。这节将介绍几种路由不会处理请求的情况。
URL模式匹配一个有效的物理文件[A Physical File is Found that Matches the URL Pattern]
默认情况下,路由不会处理请求时,将其映射到Web服务器上一个已存在的物理文件。例如,如果存在一个物理文件Products/Beverages/Coffee.aspx,路由就不会处理请求http://server/application/Products/Beverages/Coffee.aspx。路由即使如下定义{controller}/{action}/{id},也能匹配该请求,它也不会处理该请求。
如果你希望路由能处理所有请求,即使请求指向一个文件,你可以通过设置对象RouteCollection的属性RouteExistingFiles为true来重写默认行为。当你将这个值设置为true则所有与定义路由模式匹配的请求都会被路由处理。
显式禁用路由[Routing Is Explicitly Disabled for a URL Pattern]
你也可以指明路由不处理某些URL请求。定义一个路由并指明由类StopRoutingHandler处理该模式,以阻止路由处理某些请求。当一个请求被StopRoutingHandler对象处理时,StopRoutingHandler对象块会为请求添加一些额外的信息。相反,这个请求会被当作一个ASP.NET页面、Web服务或是其他ASP.NET终端处理。你可以使用方法RouteCollection.Ignore(MVC应用程序中RouteCollectionExtensions.IgnoreRoute)来创建使用类 StopRoutingHandler的路由。下面演示如何阻止对WebResource.axd文件的请求。
public static void RegisterRoutes(RouteCollection routes)
{
routes.Ignore("{resource}.axd/{*pathInfo}");
}
URL是如何被路由匹配的[How URLs Are Matched to Routes]
当路由开始处理URL请求时,它为尝试着将请求匹配到一条路由规则上。一条路由规则能否匹配URL请求取决与以下条件:
- 在你的项目中是否包含自定义的路由规则或者默认路由。
- 集合Routes中添加路由规则的顺序。
- 为路由规则添加的默认值。
- 为路由规则添加的约束。
- 是否定义了匹配对物理文件请求的路由。
为了避免不合适的路由处理了请求,在定义路由规则时一定要考虑所有这些条件。集合 Routes中Route对象出现的顺序也应仔细思考。路由集合中从第一项到最后一项依次尝试的路由匹配。当有一个匹配成功,不再对后续路由尝试匹配。通常,添加路由时应先添加最具体的,最后添加最不明确的规则。
例如你添加了如下路由规则:
- 路由规则1,{controller}/{action}/{id}
- 路由规则2, products/show/{id}
路由2绝不会处理请求,因为路由1会最先尝试匹配,并且与路由2匹配的请求在它上面也总是可以工作。例如请求http://server/application/products/show/bikes看起来好像和路由2更匹配,但是它会被路由1解析,解析结果如下:
- controller is products.
- action is show.
- id is bikes.
当请求的参数缺少时,默认值就能起作用。然而,它们可能会匹配到并非你所愿的请求。例如,假如添加如下两条路由规则:
- 路由1:{report}/{year}/{month},year,month带有默认值。
- 路由2:{report}/{year},year有默认值。
路由2将绝无处理请求的机会。路由1希望能按月份匹配,而路由2则希望是按年度。但是,路由1中的默认值会让所有匹配路由2的请求在路由1中也能工作。
你可以在路由中包含常量来避免这种歧义,例如annual/{report}/{year}和monthly/{report}/{year}/{month}。
如果一个URL不能匹配到在RouteTable集合中的任何一个Route对象,ASP.NET路由将不会处理该请求。
九、 从路由创建URL[Creating URLs from Routes]
如果你想要创建一个链接到你站点页面的超链接,你可以使用URL模式编程创建符合路由的URL。当你修改了路由模式,URL会自动匹配到新的模式上。
十、 在路由页面访问URL参数[Accessing URL Parameters in a Routed Page]
参见:https://msdn.microsoft.com/en-us/library/dd535620.aspx
https://msdn.microsoft.com/en-us/library/dd394711.aspx
十一、 配置路由环境[Configuration Settings for Routing]
ASP.NET中,要让应用程序支持路由功能,需要添加如下配置:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<!-- more -->
</modules>
</system.webServer>
</configuration>
当runAllManagedModulesForAllRequests为true时,如下URLhttp://mysite/myapp/home,即使URL中没有.aspx,.mvc或者其他扩展名,该请求也能到达ASP.NET。
然而,IIS7的更新导致不必添加配置项runAllManagedModulesForAllRequests,因为它本来就支持ASP.NET路由功能。
如果你的站点运行在IIS7且IIS已更新,你就不必设置该配置项为true。事实上,并不推荐设置它,因为它为所有请求增加了不必要的操作。如果设置该配置为true,所有请求,包括.htm,.jpg和其他静态文件都会通过ASP.NET请求通道。
默认runAllManagedModulesForAllRequests为false。如果网站配置文件中没有明确将其设置为true,而你又在未安装SP1的Windows 7,不包含必要更新的IIS7中运行你的网站。 结果就是,你会看到路由不会工作的错误提示。如果路由中存在一些问题,你可以试试下面的方法:
- 将Windows 7更新到SP1,因为它添加了IIS7的更新。
- 安装微软件在先前文章中的描述的更新。
- 在Web.Config文件中设置runAllManagedModulesForAllRequests为true。注意这会添加一些额外开销。
十二、 ASP.NET路由与安全性[ASP.NET Routing and Security]
授权规则可应用于单独映射的路由URL或同时映射的路由URL和物理URL。例如,授权规则可以声明所有用户都可以访问以开头Category的URL,但是只有管理员才能访问Categories.aspx页面。如果路由URL模式contoso.com/Category/{controller}/{action} 映射到物理地址contoso.com/Categoriespage.aspx,你只能为路由地址添加授权规则,当用一个路由地址请求过之后,所有用户都被允许可访问Categoriespage.aspx。然而,当使用物理地址请求之后,只有管理才有权限访问。
默认情况下,授权规则应用于路由地址和物理地址。
十三、 ASP.NET Web Form和路由安全性[ASP.NET Web Forms and Route Security]
在ASP.NET Web窗体应用程序中,你不应该将站点的安全性全寄托在路由授权规则,因为它们可能留下一些未保护处理的物理地址。
十四、 ASP.NET MVC和路由安全性[ASP.NET MVC and Route Security]
你不能使用路由或web.config文件保证MVC应用程序的安全性。唯一能保证MVC应用安全的做法是给所有控制器应用特性 AuthorizeAttribute ,并在登录和注册的方法(action)上应用特性AllowAnonymousAttribute 。
十五、 参考类[Class Reference]
Class |
Description |
Represents a route in a Web Forms or MVC application. |
|
Represents a route in a Dynamic Data application. |
|
Serves as the base class for all classes that represent an ASP.NET route. |
|
Stores the routes for an application. |
|
Provides methods that enable you to manage a collection of routes. |
|
Provides additional methods that enable you to manage a collection of routes in MVC applications. |
|
Contains the values for a requested route. |
|
Contains information about the HTTP request that corresponds to a route. |
|
Provides a way to specify that ASP.NET routing should not handle requests for a URL pattern. |
|
Provides a way to define routes for Web Forms applications. |
|
Provides a way to store route Constraints, Defaults, and DataTokensobjects. |
|
Provides a way to generate URLs from route information. |
十六、 ASP.NET路由VS URL重写[ASP.NET Routing versus URL Rewriting]
ASP.NET路由与URL重写不同。URL重写方式处理到达的请求时,先修改其URL再将请求发送至Web页面。例如,一个应用程序中可能使用URL重写将/Products/Widgets/修改为/Products.aspx?id=4。同时,URL重写的特点是没有基于你的模式创建URL的API。使用URL重写,如果你需要个性URL规则,你不得不手动更新所有相关联的超链接。
使用ASP.NET路由,在处理到达的请求时URL不会发生变化,因为路由功能可能从URL中提取值。当你需要创建一个URL时,给一个方法传入参数值就能为你生成URL。修改URL规则,只需要调整一个地方,你在应用程序中创建的所有链接都会自动使用新规则。
ASP.NET路由[ASP.NET Routing]的更多相关文章
- 返璞归真 asp.net mvc (2) - 路由(System.Web.Routing)
原文:返璞归真 asp.net mvc (2) - 路由(System.Web.Routing) [索引页] [源码下载] 返璞归真 asp.net mvc (2) - 路由(System.Web.R ...
- ASP.NET路由模型解析
大家好,我又来吹牛逼了 ~-_-~ 转载请注明出处:来自吹牛逼之<ASP.NET路由模型解析> 背景:很多人知道Asp.Net中路由怎么用的,却不知道路由模型内部的运行原理,今天我就给大家 ...
- Asp.Net MVC 路由 - Asp.Net 编程 - 张子阳
http://cache.baiducontent.com/c?m=9d78d513d98316fa03acd2294d01d6165909c7256b96c4523f8a9c12d522195646 ...
- ASP.NET没有魔法——ASP.NET MVC 路由的匹配与处理
ASP.NET MVC的路由是MVC应用的一个核心也是MVC应用处理的入口,作为一个开发者,在正常情况下仅仅需要做的就是根据需求去定义实体.业务逻辑,然后在MVC的Controller中去调用.Vie ...
- ASP.NET Web API 框架研究 ASP.NET 路由
ASP.NET Web API 如果采用Web Host方式来寄宿,在请求进入Web API 消息处理管道之前,就会用ASP.NET 自身的路由系统根据注册的路由表,解析出当前请求的HttpContr ...
- ASP.NET MVC , ASP.NET Web API 的路由系统与 ASP.NET 的路由系统是怎么衔接的?
ASP.NET MVC 的路由实际上是建立在 ASP.NET 的路由系统之上的. MVC 路由注册通常是这样的: RouteTable 是一个全局路由表, 它的 Routes 静态属性是一个 Ro ...
- 我的IIS7.5竟然不支持ASP.NET路由
MVC模式下那些友好,屏蔽具体物理文件的URL让我眼馋,咱也想在WEB FORM项目用上一用. 按照指引,添加global.asax,写上路由代码什么的: <%@ Application Lan ...
- ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 路由 前两章节中,我们提到 ASP.NET Core 支持 MVC 开发 ...
- 路由 - ASP.NET MVC 4 系列
软件开发人员常常对一些细小的细节问题倍加关注,由其在考虑源代码的质量和结构时更是如此.因此,当遇到大部分使用 ASP.NET 技术构建的站点,使用如下的 URL 地址时,可能会有些奇怪: ...
随机推荐
- html中table边框属性
1.向右(横向)合并: <td colspan="5"><span>后台管理系统</span></td> 2.向下(纵向)合并: & ...
- error C4430:missing type specifier 解决错误
错误 3 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int ...
- spring的BeanFactory加载过程
ApplicationContext spring = new ClassPathXmlApplicationContext("classpath*:spring/applicationCo ...
- JavaScript学习笔记(四)——jQuery插件开发与发布
jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用, ...
- XAMARIN ANDROID 二维码扫描示例
现在二维码的应用越来越普及,二维码扫描也成为手机应用程序的必备功能了.本文将基于 Xamarin.Android 平台使用 ZXing.Net.Mobile 做一个简单的 Android 条码扫描示 ...
- Maven安装
开发分布式的商场系统,用到了一些新的技术,做一个记录和分享 这里讲一下maven安装 首先什么是Maven Maven作为一个构建工具,不仅帮我们自动化构建,还能抽象构建过程,提供构建任务实现.他跨平 ...
- 我的MYSQL学习心得(十一) 视图
我的MYSQL学习心得(十一) 视图 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- XSS 前端防火墙 —— 整装待发
到目前为止,我们把能用前端脚本防御 XSS 的方案都列举了一遍. 尽管看起来似乎很复杂累赘,不过那些是理论探讨而已,在实际中未必要都实现.我们的目标只是为了预警,能发现问题就行,并非要做到滴水不漏的程 ...
- SQL优化案例—— RowNumber分页
将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...
- ECMASCript2015 提案 stage-3的对象展开运算符
看源码时看到如下的代码 export default { //通过mapActions将actions映射到methods里 methods: { ...mapActions([ 'updateSta ...