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参数或一些其他约束

转载于:https://www.cnblogs.com/tianguook/p/3969876.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/575229.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python编写arcgis脚本教程_ArcGIS使用Python脚本工具

在Pyhton写的一些代码,用户交互不方便,用户体验比较差,不方便重用。在ArcGIS中可以将用写的Python代码导入到ToolBox中,这样用起来就比较方便了。这里用按要素裁剪栅格的Python来演示如何导入ArcGIS中。代码如下: impo…

初步认识java中的方法

java中方法: 方法:是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能。需要这个功能的时候,就可以去调用。这样即实现了代码的复用,也解决了代码冗余的问题。 public class Methods…

python中可以使用变量来引用函数吗_如何在python语言中使用函数变量并调用函数...

在python语言中,除了常规变量之外,还有函数变量。把函数本身赋值给变量,这个变量为函数变量。工具/原料 python pycharm 截图工具 WPS 方法/步骤 1 在已新建的python文件中,定义函数mul_data,传入两个参数param和exp2 …

ACM竞赛常用STL(二)之STL--algorithm

<algorithm>无疑是STL 中最大的一个头文件&#xff0c;它是由一大堆模板函数组成的。下面列举出<algorithm>中的模板函数&#xff1a; adjacent_find / binary_search / copy / copy_backward / count/ count_if / equal / equal_range / fill / fill_n / find /fi…

C语言程序设计现代方法1,2,3章

1&#xff1a;浮点型&#xff08;float&#xff09;运算比int慢&#xff0c;并且可能存在舍入误差 如float存储0.1&#xff0c;以后使用可能会变成0.099999999987 2&#xff1a;宏定义只用大写&#xff0c;这是大多数C程序猿遵循的规范&#xff01; C语言区分大小写&#xff0c…

python全栈要学什么_python全栈要学什么 python全栈学习路线

IT行业&#xff0c;技术要比学历、年龄、从业经验更为重要&#xff0c;技术水平直接决定就业薪资&#xff0c;想要学好python&#xff0c;首先要先了解精通Python语言基础、Python web开发、Python爬虫、Python数据分析这四大方面。 全栈即指的是全栈工程师&#xff0c;指掌握多…

初识java中数组、数组在内存中、越界异常、空指针异常

数组&#xff1a; 当存储多个数据时&#xff0c;此时可能会使用多个变量&#xff0c;这样不断声明变量会很麻烦&#xff0c;而这些变量都有相似的特性&#xff0c;因此我们可以将它们存放到一个容器中&#xff0c;统一处理。 容器&#xff1a;是将多个数据存储到一起&#xf…

异常处理python 空气质量问题_python的异常处理

异常处理什么是异常&#xff1f;首先要清楚&#xff0c;什么是异常&#xff0c;异常就是程序运行时发生错误的信号(在程序出现错误时&#xff0c;则会产生一个异常&#xff0c;若程序没有处理它&#xff0c;则会抛出该异常&#xff0c;程序的运行也随之终止)&#xff0c;在pyth…

Android获取屏幕实际高度跟显示高度,判断Android设备是否拥有虚拟功能键

//获取屏幕尺寸&#xff0c;不包括虚拟功能高度 getWindowManager().getDefaultDisplay().getHeight();获取屏幕原始尺寸高度&#xff0c;包括虚拟功能键高度&#xff0c; private int getDpi(){ int dpi 0;Display display getWindowManager().getDefaultDisplay();Displa…

cad小插件文字刷_文字狗最佳排版神器 小恐龙公文排版助手Office WPS插件

文字狗最佳排版神器文字狗最佳排版神器 小恐龙公文排版助手Office WPS插件1.85最新版 无需注册、无需其他费用、无广告。相信大家所需要提交的各种论文、报告等Word文档都对格式有着非常严格的要求&#xff0c;对标题、目录、正文都有不同的要求。尤其是对于公文&#xff0c;要…

Java中的对象、private关键字、this关键字、构造方法

面向对象 概述&#xff1a;Java一种面向对象的程序设计语言&#xff0c;面向对象思想是一种程序设计思想&#xff0c;在面向对象思想的指引下&#xff0c;使用Java语言去设计、开发计算机程序。 这里的对象泛指现实中一切事物&#xff0c;每种事物都具备自己的属性和行为。 …

2060显卡驱动最新版本_教程:怎么安装更新NVIDIAAMD显卡驱动?

PART-1:装驱动这么简单的事情真的需要写教程吗&#xff1f;我自己都理解不了我为什么要写这样一个教程&#xff0c;但是如你所见&#xff0c;他确实被我写出来了&#xff0c;而且对大部分人都挺有用。首先&#xff0c;使用鲁大师以及驱动精灵这类软件的同学自己喜欢就好&#x…

C语言实现泛型编程

http://www.cnblogs.com/archimedes/p/c-general-function1.html转载于:https://www.cnblogs.com/LittleTiger/p/3980416.html

中电福富外包offer要等多久_记一次外包经历

开题&#xff0c;我是知道外包很坑的&#xff0c;无论从待遇&#xff0c;体验&#xff0c;未来职业发展&#xff0c;那都是非常负面的。最近随家人&#xff08;二孩都需要照顾&#xff09;搬到弱二线城市&#xff0c;想找个开发岗&#xff0c;招聘网上基本都被外包包场了&#…

mysql 两个时间相差大于24小时的数据_MySQL 主从同步延迟的原因及解决办法(仅学习)...

原文链接&#xff1a;https://blog.csdn.net/hao_yunfeng/article/details/82392261Mysql主从基本原理&#xff0c;主要形式以及主从同步延迟原理 (读写分离)导致主库从库数据不一致问题的及解决方案 一、主从数据库的区别 从数据库(Slave)是主数据库的备份&#xff0c;当主数据…

分形之万花筒

万花筒是一种光学玩具&#xff0c;只要往筒眼里一看&#xff0c;就会出现一朵美丽的“花”样。将它稍微转一下&#xff0c;又会出现另一种花的图案。不断地转&#xff0c;图案也在不断变化&#xff0c;所以叫“万花筒”。万花筒的图案是靠玻璃镜子反射而成的。它是由三面相交成…

java中常用API、Scanner类、匿名对象、Random类、ArrayList类、对象数组

java中常用API&#xff1a; API&#xff1a;Application Programming Interface&#xff0c;应用程序编程接口。Java API是JDK中提供给我们使用的类的说明文档。这些类将底层的代码实现封装了起来&#xff0c;我们不需要关心这些类是如何实现的&#xff0c;只需要知道如何使用…

数字图像处理课设图像的锐化_数字图像处理图像锐化处理.ppt

数字图像处理图像锐化处理4.7.2 灰度级到彩色转换 灰度级到彩色转换(例) 在HSI彩色空间的直方图均衡强度均衡处理没有改变图像的色调和饱和度值&#xff0c;但它的确影响了整体图像的彩色感观。 向量分量可以用传统的灰度邻域处理单独地平滑RGB图像的每一平面得到。 用拉普拉斯…

Java中String类、字符串常量池、字符串常用方法

String类&#xff1a; String代表字符串类&#xff0c;java中所有双引号中的内容都称为字符串&#xff0c;如&#xff1a;“hello”。字符串是不可改变的&#xff0c;因此字符串是可以共享使用的&#xff0c;相当于char字符数组&#xff0c;但是底层原理是byte字节数组。 创建…

mysql同步数据到另一张表_mysql:Otter跨机房数据同步(单向)

重要说明&#xff1a;需要同步的表必须要有主键 主键 主键otter是一款基于Java且免费、开源基于数据库增量日志解析&#xff0c;准实时同步到本机房或异地机房的mysql/oracle数据库的解决方案。Otter目前支持了什么1. 单向同步&#xff0c; mysql/oracle互相同步2. 双向同步&am…