ASP.NET MVC3 学习心得------路由机制
9.1 理解URL
URL满足的要求:
l 域名易于记忆和拼写
l 简短、易输入
l 可以反应出站点的结构
l 可破解,用户可以通过移除URL的末尾,进而达到更高层次的信息体系结构
l 持久、不能变化
9.2路由机制的概述
ASP.NET MVC中路由机制的两种用途:
l 匹配传入的请求,并映射到控制器的操作
l 构造传出的URL,用来相应控制器的操作
9.2.1 对比路由和URL重写
URL重写是将URL映射到另一个URL
路由是将URL映射到资源
两者的区别:路由机制也使用它在匹配传入URL时同样的映射规则来帮助生成URL,而URL重写只能用于传入的请求URL,而不能帮助生成原始的URL
9.2.2 路由的定义
路由的定义是从URL模式开始的,因为它指定了与路由相匹配的模式,路由可以指定它的URL及其默认值,还可以约束URL的各个部分,提供关于路由如何、何时、传入的请求URL相匹配的严格控制
路由URL
我们在新建的应用程序中的Global.asax.cs文件的Application_Start方法中调用了一个RegisterRoutes方法,如下:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
} // 参数默认值
);
}
如:routes.MapRoute("Default","{first}/{second}/{third}");
在两个斜杠之前的花括号为占位符,这些占位符即是URL参数,该示例定义的规则可以匹配任何带有3个段的URL,我们可以将这些参数命名为任何想要的名称,当客户端请求到达服务器时,路由将解析请求的URL,并将解析出的路由参数值放入字典中
2、路由值
我们可以使用任何想要的名称定义路由,但是为了程序的正确的运行ASP.NET MVC 框架要求使用一些特定的参数名--{controller}和{action}
{controller}为处理请求的控制器,ASP.NET MVC 规定将Controller后添加到{Controller}URL参数值的后面构成一个类型名称,然后根据名称查找实现了System.Web.Mvc.IController接口的类型
如下示例:routes.MapRoute{"Default","{controller}/{action}/{id}");
路由URL在段中也允许包含字面值,如将MVC集成到一个现有的站点中并想要所有的MVC请求一site开头 则如下:site/{controller}/{action}/{id}
所以该路由只能匹配site/Home/index/123 而不是匹配/Home/index/231
此外,URL段中还允许字面值和参数混在一起,但是它不允许有两个连续的URL参数,
如下:{language}-{country}/{controller}/{action}
{controller}.{action}.{id}
有时只需要匹配两个参数,这个时候我们不需要在重写路由了,只需要将第三个参数换为可选参数就行
如下:routes.MapRoute("Default","{controller}/{action}/{id}",new {id=Urlparameter.Optional});
我们也可以为多个参数提供默认值:
如:routes.MapRoute("Default","{controller}/{action}/{id}",new {id=Urlparameter.Optional,action=“index"});
路由URL模式、默认值及其匹配
路由URL模式 默认值 匹配URL模式示例
{controller}/{action}/{id} new {id=UrlParameter.Optional} /albums/diplay/123
/albums/diplay
{controller}/{action}/{id} new {id=UrlParameter.Optional, /albums/display/123
Action="index", /albums/display
Id=UrlParameter.Optional} /albums
/
4、路由约束
有时候需要对指定URL段的数量来说,我们需要对URL有更多的控制
如下URL:
l http://example.com/2008/01/16
l http://example.com/posts/categories/aspnetmvc/
以上的两个URL都包含3个段,且都可以和默认路由匹配,但是如第一个URL要匹配一个2008controller的控制器,这样是错误的,因此需要对路由进行约束,:
如:
routes.MapRoute("blog", "{year}/{month}/{day}", new
{
controller = "blog",
action = "index"
}, new
{
year = @"\d{4}",
month = @"\d{2}",
day = @"\d{2}"
});
routes.MapRoute("simple", "{controller}/{action}/{id}");
路由机制自动的使用^和$符号包装指定的约束表达式,以确保表达式能够精确的匹配参数值
在本示例中,我们在默认的simple路由之前添加的新路由,路由按先后顺序与传入的URL进行匹配,直到匹配成功,因为/2008/01/16的请求将与两个定义的路由都匹配,所以我们把更具体的路由放在了前面
9.2.3 命名路由
为路由指定名称可以解决URL的路由二义性问题
如:
routes.MapRoute(name: "Test", url: "code/p/{action}/{id}", defaults: new
{
controller = "Section",
action = "Index",
id = ""
});
routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new
{
controller = "Home",
action = "Index",
id = ""
});
在视图中生成指向路由的超链接如下:
@Html.RouteLink("Test", new
{
controller = "section",
action = "Index",
id = 123
});
@Html.RouteLink("Default", new
{
controller = "Home",
action = "Index",
id = "123"
});
该方法不能指定由哪个路由来生成链接
为此我们做如下修改:
@Html.RouteLink(linkText: "Route:Test", routeName: "Test", new
{
controller = "section",
action = "Index",
id = "123"
});
@Html.RouteLink(linkText: "Route:Default", routeName: "Default", new
{
controller = "Home",
action = "Index",
id = "123"
});
这样我们便可以为生成的URL指定路由名来生成相应的URL
9.2.4 MVC区域
在路由没有指定名称空间的情况下,很容易产生二义性,即两个同名的控制器同时匹配一个路由,我们可以通过在项目中使用唯一的控制器名称来防止二义性,如下:对特定的路由指定一组用来定位控制器的名称空间
routes.MapRoute{"Default","{controller}/{action}/{id}",new {controller="Home",action="Index",id=""},new []{ "AreasWeb.Controllers"});
第四个参数指定一个名称空间数组
9.2.5 Catch-All 参数
Catch-all参数允许路由匹配具有任意数量的段的URL,参数中的值是不含查询字符串的URL剩余部分
如:
routes.MapRoute("CatchAllRoute", "/query/{query-name}/{*extrastuff}");
匹配如下:
URL 参数值
/query/select/a/b/c extrastuff="a/b/c"
/query/select/a/b/c/ extrastuff="a/b/c"
/query/select/ extrastuff=""(路由仍然匹配,“catch-all捕获了空字符串
9.2.6 段中的多个URL参数
路由的URL中可以存在多个参数,如下:
l {title}-{artist}
l Album{title}and{artist}
l {filename}.{ext}
为避免二义性,参数不能临近,
如下:均为无效的URL
l {title}{atrist}
l DownLoad{filename}{ext}
路由URL在与传入的请求匹配时,它的字面值与请求精确匹配,而其中的URL参数是贪婪匹配,路由使每个URL参数尽可能的匹配更多的文本
如下: 多参数路由匹配
路由URL 请求的URL 路由数据的结果
{finename}.{ext} /Foo.xml.aspx filename="Foo.xml" ext="aspx"
My{title}-{cat} /MyHouser-dwelling title="Houser" ext="dwelling"
{foo}xyz{bar} /xyzxyzxyzblah foo="xyzxyz" bar="blah"
9.2.7 StopRoutingHandler和IgnoreRoute
默认情况下,路由机制将忽略那些映射到磁盘物理文件的请求。
方法如下:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//第一种方法
routes.Add(new Route("{resource}.axd/{@pathInfo}",new StopRoutingHandler()));//第二种方法
}
9.2.9 揭秘路由如何生成URL
1、URL生成的高层次概述
路 由机制的核心是一个基于RouteCollection类和RouteBase类组成的简单抽象对象组成的算法。有许多中生成URL的方法,但是这些方法 都是以调用RouteCollection.GetVirtualPath方法的重载版本而结束的,该方法的重载版本如下:
Public virtualPathData GetVirtualPath(RequestContext requestContext,RouteValueDictionary values)
Public virtualpathData GetVirtualPath(RequestContext requestContext,string name,RouteValueDictionary values)
第一个重载版本接受当前的RequestContext以及由用户指定用来选择想要的路由值
l 路由集合通过Route.GetVirtualPath方法遍历每个路由,类似于在路由与传入的请求匹配时所运用的匹配逻辑
l 如果一个路由匹配,则返回一个包含了URL的VirtualPathData实例,及其他匹配信息,否则将返回空值,路由机制移向列表中的下一个路由
第二个重载版本接受了三个参数,第二个参数为路由名称,在路由集合中路由名称是唯一的,指定了路由名称之后便不需要遍历每个路由,直接找到指定名称的路由进行匹配,如果匹配则返回VirtualPathData实例,否则返回空值
2、URL生成详解
① 用户调用RouteCollection.GetVirtualPath方法,并向它传递一个RequestContext对象、一个包含值的字典,以及用来选择生成URL路由的名称(可选参数)
② 路由机制查看要求的路由URL参数,并确保提供的路由值字典为每一个要求的参数提供一个值,否则URL生成程序立即中止,返回空值
③ 一 些路由可能包含没有对应的URL参数的默认值。如:路由可能为category见提供了 一个默认值"pastries",但是category不是路由 URL的一个参数,这时,如果用户传入的路由值字典为category提供了一个值,那么该值必须匹配category的默认值
④ 路由机制然后应用路由的约束,如果有的话,要查找约束
⑤ 路由匹配成功,可以通过查看每一个URL参数,并尝试用字典中的对应值填充它,进而生成URL
3、外界路由值
在一些情形中,URL生成程序还可以利用那些不是通过调用GetVirtualPath方法显示提供的值
4、溢出参数
指在URL生成过程中使用、但是在路由定义中却没有指定的路由值。具体指的是路由的URL、默认的字典和约束字典
如:路由定义如下:
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
} // 参数默认值
);
上面路由的定义中不包括名为“page”的URL参数,下面我们使用Url.RouteUrl方法渲染了URL,而不是生成连接:
@Url.RouteUrl(new {controller="Report",action="List",page="123"});
5、该 行代码生成的URL是:/Request/List?Page=2,但是我们指定的参数比需要的参数还要多,这个时候额外的参数会作为查询字符串附加在生 成的URL之后,路由机制在选择匹配的路由时并不是精确的匹配,它只是选择足够的匹配的路由,只要指定的参数满足路由需要,额外参数无关紧要
6、Route类生成URL的若干示例
routes.MapRoute("report", "reports/{year}/{month}/{day}", new{day = 1});
则GetVirtualPath方法调用示例如下:
参数 返回URL 说明
Year=2007,month=1,day=1 /reports/2007/1/1 直接匹配
Year=2007,month=1 /reports/2007/1 默认day=1
Year=2007,month=1, /reports/2007/1/1?Category=123 溢出参数进入生成的URL
day=1,category=123
Year=2007 返回空值 因为没有提供足够的匹配参数
9.3 揭秘路由如何绑定到操作
9.3.1 高层次请求的路由管道
主要由以下几步组成:
① UrlRoutingModule 尝试使用在RouteTable中注册的路由匹配当前请求
② 如果一个路由匹配成功,那么路由模块将从匹配成功的路由中获取IRouteHandler接口对象
③ 路由模块由IRouteHandler接口的GetHandler方法,并返回用来处理请求的IHttpHandler对象
④ 调用HTTP处理程序中的ProcessRequest方法,将要处理的值传给它
⑤ 在 ASP.NET MVC 中,IRouteHandler是MvcRouteHandler类的一个实例,MvcRouteHandler转而返回一个实 现了IHttpHandler接口的MvcHandler对象,返回的MvcHandler对象主要用来实例化控制器,并调用该实例化控制器上的方法
9.3.2 路由数据
调 用GetRouteData方法将返回一个RouteData的实例,RouteData包含了关于匹配请求的路由的信息,如果匹配成功则会创建一个字 典,其中包含从URL中解析出的信息,并且路由还会为URL中的每一个参数向字典中添加一个键,如:{controller}/{action} /{id},所在的字典中至少包含三个键分别为controller、action、id
9.4 自定义路由约束
之前我们讲过可以使用正则表达式对路由进行细粒度的匹配控制,除此之前路由机制提供了一个具有单一Match方法的IRouteConstraint接口,该接口定义如下:
public interface IRouteConstraint
{
bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection);
}
当路由机制评估路由约束时,如果约束值实现了IRouteConstraint接口,那么这将导致路由机制引擎调用路由约束上的IRouteConstraint.Match方法,以确定约束是否满足给定的请求。
路由机制本身以HttpMethodConstraint类的形式提供了IRouteConstraint接口的一个实现。如下:定义一个路由只相应GET请求,其他请求不响应
routes.MapRoute("name", "{controller}", null, new
{
httpMethod = new HttpMethodConstraint("GET")
});
自定义的约束没有必要关联URL参数,因此可以提供一个基于多个URL参数或一些其他约束
ASP.NET MVC3 学习心得------路由机制的更多相关文章
- ASP.NET MVC3学习心得-----表单和HTML辅助方法
5.1表单的使用 5.1.1 action和method的特性 表单是包含输入元素的容器,包含按钮.复选框.文本框等元素,表单的这些输入元素使得用户能够向页面中输入信息,并把输入信息提交给服务器.A ...
- 一步步学习ASP.NET MVC3 (14)——Route路由
请注明转载地址:http://www.cnblogs.com/arhat 由于今天是星期六,所以多写几篇,感觉前几天的忙碌没有及时发布文章,趁着周末老魏尽力的多写几篇文章.因为本系列基本上快结束了,所 ...
- ASP.NET MVC学习之路由篇(3)
根据路由输出链接 既然是网站开发自然少不了链接,我们已经学会了强大的路由,但是还缺少一步就是能够将这些路由的路径输出到页面,下面我们就开始学习如何输出路由路径. 首先我们的路由注册部分如下所示: 1 ...
- ASP.NET MVC学习之路由篇(2)
7.解决与物理路径的冲突 当发送一个请求至ASP.NET MVC时,其实会检查网站中存不存在这个请求的物理路径文件,如果存在的话,就会直接将这个物理文件返回.但是有时候我们需要它执行控制器的某个方法, ...
- ASP.NET MVC学习之路由篇(1)
1.基本路由 RouteConfig.cs: 1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteColle ...
- ASP.NET MVC4学习笔记路由系统概念与应用篇
一.概念 1.路由是计算机网络中的一个技术概念,表示把数据包从一个网段转发至另一网段.ASP.NET中的路由系统作用类似,其作用是把请求Url映射到相应的"资源"上,资源可以是一段 ...
- ASP.NET MVC学习之路由篇
约束路由 上面我们有一个{id}用来捕获参数的,但是你也发现了它可以捕捉任何字符串等等,但是我们有时需要限制它,比如让它只能输入数字,那么我们就可以使用正则表达式去约束它. 如下修改RouteConf ...
- ASP.NET MVC 学习之路由(URL Routing)
在ASP.NET MVC中,一个URL请求是由对应的一个Controller中的Action来处理的,由URL Routing来告诉MVC如何定位到正确的Controller和Action. 默认路由 ...
- ASP.NET MVC4学习笔记路由系统实现
一.路由实现 路由系统实际是一个实现了ASP.NET IHttpModule接口的模块,通过注册HttpApplication的PostResolveRequestCache 事件对Url路由处理.总 ...
随机推荐
- handlebars.min.js的使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 配置lambda
=========== 添加 apply plugin: 'me.tatarka.retrolambda' 添加 compileOptions { sourceCompatibilit ...
- Codeforces Round #505 (Div 1 + Div 2) (A~D)
目录 Codeforces 1025 A.Doggo Recoloring B.Weakened Common Divisor C.Plasticine zebra D.Recovering BST( ...
- 使用 IntraWeb (2) - Hello IntraWeb
IntraWeb 比我相像中的更贴近 VCL, 传统的非可视组件在这里大都可用(其内部很多复合属性是 TStringList 类型的), 它的诸多可视控件也是从 TControl 继承下来的. 这或许 ...
- 通过Windows Compatibility Pack补充.net core中缺失的api
把项目往.net core上迁移的时候,一个最大的问题就是和.net framework相比,有一部分api缺失.它主要分为两类: Windows 独有的api,如注册表 未完成的功能,如System ...
- 大数据以及Hadoop相关概念介绍
一.大数据的基本概念 1.1.什么是大数据 大数据指的就是要处理的数据是TB级别以上的数据.大数据是以TB级别起步的.在计算机当中,存放到硬盘上面的文件都会占用一定的存储空间,例如: 文件占用的存储空 ...
- TF400511: Your team has not defined any iterations to use as sprints
tfs里面的冲刺对于开发团队来说, 是非常重要的一个功能,是团队开发进度的晴雨表: 但是如果从此死活出不来,怎么办呢? TF400511:您的团队尚未定义任何要用作冲刺 (sprint) 的迭代 TF ...
- AutoMapper在MVC中的运用02-Decimal转String、集合、子父类映射
本篇AutoMapper使用场景: ※ Decimal转换成String类型 ※ 源数组转换成目标数组 ※ 源中的集合(数组)属性转换成目标中的集合(数组)属性 ※ 子类父类间的映射 Decimal转 ...
- TMS WEB CORE直接从HTML&CSS设计的页面布局
TMS WEB CORE直接从HTML&CSS设计的页面布局 TMS WEB CORE支持DELPHI IDE中拖放控件,生成HTML UI.这种方式适合DELPHI和C++ BUILDER的 ...
- C# 其他图片格式转emf
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...