浅谈Route规则名称的作用,及MvcPatch的处理方式
2009-10-13 10:00
513 查看
国庆前的最后一天,我写了《关于ASP.NET Routing的几点内容》,其中谈论了ASP.NET Routing作用,设计目的,工作流程等等。不过我还有一个比较重要的东西一笔带过了,不知道您注意到了没有,在向ASP.NET Routing的RouteTable.Routes属性(一个RouteCollection对象)中添加Route规则的时候,我们会同时指定一个“名称”,在微软给出的官方“广告”中,似乎看不出这个名称有什么用。但事实上,它的功能非常关键。
那么我们通过一个实际的例子来看一下,Route规则的“名称”到底有什么作用:
以上两个Route规则,分别是“文章(article)”和“产品(product)”的搜索URL。与微软“广告”中一直使用的{controller}/{action}/{id}不同,我们实际生产过程中,一些如controller或action这样的数据无法从URL中捕获到,因此我们只是“匹配URL”并且“指定默认值”。就“捕获URL”这方面,这样的配置非常完美。但是我也多次强调,Route规则还会负责“生成虚拟路径”。那么这样的配置在这方面会有什么问题呢?请看下面这个数据:
我们可以使用这个匿名对象来构造一个RouteValueDictionary,其中包含了生成虚拟路径所需要的数据。于是我们可能会调用这个方法来得到结果:
很显然,这个数据是要生成“产品”的搜索路径,但是您猜一下,我们能够得到正确结果吗?
不行。
因为RouteCollection的GetVirtualPath方法会依次遍历其中所有Route对象,访问其GetVirtualPath方法,并把第一个非null参数作为结果。如果项目中的配置如以上两个,则这样的数据永远会被Article.List这个规则捕获到——于是生成的永远便是Article.List的虚拟路径了。
对于这个问题一般有两种解决方法,一是为Route规则添加“约束”:
于是,这个Route对象在生成虚拟路径的时候,就会关注当前的RouteValueDictionary中包含的值是否符合约束。如果不符合,则直接返回null。如此,RouteCollection便会继续尝试下一个Route规则——可能就是Product.List,于是我们得到了想要的数据。
第二种解决方法便是在构造URL的时候指定一个名称:
如此,RouteCollection便会直接去找到Product.List所对应的Route对象,并且直接使用它的GetVirtualPath方法获得虚拟路径——即使返回null,也不会尝试其他Route规则。这么做的好处是避免Route规则之间在生成虚拟路径时产生冲突,并且由于避免了便利所造成的无效尝试,于是程序性能也会有些许提高。
在MvcPatch中也有对Route配置名称的支持:在MvcPatch.Extensions.dll中包含一个RouteNameAttribute对象,我们可以用它对某个Action方法进行标记,如:
于是,如果您在View中使用这样的方法来构造URL:
MvcPatch便会查看这个Action方法是否有RouteName标记。如果有,则通过直接指定名称的方式去构造虚拟路径,否则便还是传统的“遍历”方式。
那么我们通过一个实际的例子来看一下,Route规则的“名称”到底有什么作用:
routes.MapRoute( "Article.List", // route name "articles/{*searchCriteria}", // pattern new { controller = "Article", action = "List" }); // defaults routes.MapRoute( "Product.List", // route name "products/{*searchCriteria}", // pattern new { controller = "Product", action = "List" }); // defaults
以上两个Route规则,分别是“文章(article)”和“产品(product)”的搜索URL。与微软“广告”中一直使用的{controller}/{action}/{id}不同,我们实际生产过程中,一些如controller或action这样的数据无法从URL中捕获到,因此我们只是“匹配URL”并且“指定默认值”。就“捕获URL”这方面,这样的配置非常完美。但是我也多次强调,Route规则还会负责“生成虚拟路径”。那么这样的配置在这方面会有什么问题呢?请看下面这个数据:
var data = new { controller = "Product", action = "List", searchCriteria = "..." }
我们可以使用这个匿名对象来构造一个RouteValueDictionary,其中包含了生成虚拟路径所需要的数据。于是我们可能会调用这个方法来得到结果:
RouteTable.Routes.GetVirtualPath(requestContext, new RouteValueDictionary(data));
很显然,这个数据是要生成“产品”的搜索路径,但是您猜一下,我们能够得到正确结果吗?
不行。
因为RouteCollection的GetVirtualPath方法会依次遍历其中所有Route对象,访问其GetVirtualPath方法,并把第一个非null参数作为结果。如果项目中的配置如以上两个,则这样的数据永远会被Article.List这个规则捕获到——于是生成的永远便是Article.List的虚拟路径了。
对于这个问题一般有两种解决方法,一是为Route规则添加“约束”:
routes.MapRoute( "Article.List", // route name "articles/{*searchCriteria}", // pattern new { controller = "Article", action = "List" }, // defaults new { controller = "Article", action = "List" }); // constraints
于是,这个Route对象在生成虚拟路径的时候,就会关注当前的RouteValueDictionary中包含的值是否符合约束。如果不符合,则直接返回null。如此,RouteCollection便会继续尝试下一个Route规则——可能就是Product.List,于是我们得到了想要的数据。
第二种解决方法便是在构造URL的时候指定一个名称:
RouteTable.Routes.GetVirtualPath(requestContext, "Product.List", new RouteValueDictionary(data));
如此,RouteCollection便会直接去找到Product.List所对应的Route对象,并且直接使用它的GetVirtualPath方法获得虚拟路径——即使返回null,也不会尝试其他Route规则。这么做的好处是避免Route规则之间在生成虚拟路径时产生冲突,并且由于避免了便利所造成的无效尝试,于是程序性能也会有些许提高。
在MvcPatch中也有对Route配置名称的支持:在MvcPatch.Extensions.dll中包含一个RouteNameAttribute对象,我们可以用它对某个Action方法进行标记,如:
[RouteName("Product.List")] public ActionResult List(string searchCriteria) { ... }
于是,如果您在View中使用这样的方法来构造URL:
<%= Url.Action<ProductController>(c => c.List(...)) %>
MvcPatch便会查看这个Action方法是否有RouteName标记。如果有,则通过直接指定名称的方式去构造虚拟路径,否则便还是传统的“遍历”方式。
相关文章推荐
- Windows PE入门基础知识:Windows PE的作用、命名规则、启动方式、启动原理
- Windows PE入门基础知识:Windows PE的作用、命名规则、启动方式、启动原理
- 浅谈Python中的作用域规则和闭包
- Windows PE入门基础知识:Windows PE的作用、命名规则、启动方式、启动原理
- 浅谈JDBC批处理方式提高执行效率[转]
- C/C++函数名称修饰规则及extern "C"的作用(函数名压扎)
- 浅谈Python中的作用域规则和闭包
- text-align:justify真正作用及无效处理方式
- 浅谈Javascript事件处理程序的几种方式
- 浅谈Javascript事件处理程序的几种方式
- A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。 马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)
- 浅谈RxJava处理业务异常的几种方式
- 线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
- 浅谈JavaScript中的五种为事件指定处理程序的方式
- [FAQ08919][NW]网络运营商名称显示规则(锁屏界面,下拉列表)---网络名称 客制化方法 和 问题处理flow
- 浅谈在js传递参数中含加号(+)的处理方式
- C/C++函数名称修饰规则及extern "C"的作用
- 浅谈Javascript事件处理程序的几种方式
- 浅谈 Javascript 事件处理程序的几种方式
- Windows PE入门基础知识:Windows PE的作用、命名规则、启动方式、启动原理