新版Routing功能介绍
在ASP.NET 5和MVC6中,Routing功能被全部重写了,虽然用法有些类似,但和之前的Routing原理完全不太一样了,该Routing框架不仅可以支持MVC和Web API,还支持一般的ASP.NET5程序。新版的改变有如下几个部分。
首先,Routing系统是基于ASP.NET 5的,是一个独立于MVC的路由框架,而不是基于MVC的。MVC只是在上面扩展了一个快捷方式而已。
其次,在ASP.NET 5中,MVC和Web API控制器没有区别了,即合二为一了。两者派生于同一个Controller基类。也就是说该Routing框架是适用于两者的,适用于MVC则意味着也适用于Web API。
最后,不管在基于约定的Route声明还是基于Attribute的Route声明,都可以使用内联约束和参数选项。例如,你可以约定路由中某个参数的数据类型,也可以让一个参数标记为可选类型,再或者给其提供一个默认值。
Routing框架的主要流程
基本的Routing框架是基于Middleware来实现的,这样就可以将其添加到HTTP的请求Pipeline中了,它可以喝其它任意Middleware一起进行组合使用,如静态文件处理程序、错误页、或者SignalR服务器。
在使用Routing框架之前,首要要了解Routing的作用,作用很简单:
对于HTTP请求,Routing系统负责找出与之匹配的route,创建route数据,并将该请求派送到该route对于的处理程序(Handler)上。Controller和Action的选择,只是MVC的Handler的一个具体实现,该实现使用route数据和HTTP请求中的其它信息来选择要执行的Controller和Action。在新版的MVC6中,该处理程序的名称为MvcRouteHandler。
路由系统的执行流程如下:
ASP.NET 5监听到一个HTTP请求。然后Routing Middleware就会尝试将route集合中的route匹配该请求。一旦成功匹配一个请求,就找出该route对应的handler。调用该handler上的RouteAsync方法(因为所有的handler都要实现该接口方法)。RoutingContext有一个IsHandled标记,如果该标记设置为true,则意味着该请求已经被这个handler成功处理了;如果设置为false,则意味着该handler无法处理该请求,系统会再为此匹配一个route。
和之前的Routing系统有点不同的是,老版的Routing系统一旦成功匹配一个路由,就将其交由其对应的Handler,不管对应的Handler能不能处理该请求,所以就会出现route匹配成功了,但是找不到对应的action,此时就会出现404错误,而新版对此作出了上述第4步骤的改进(重新将控制权交回给Routing系统,进行重新匹配),看起来还是非常不错的。
Route参数和约束条件的改进
在之前的route设置中,要约束一个参数的数据类型的话,我们需要使用类型如下代码:
routes.MapRoute( "Product", "Product/{productId}", defaults: new { controller = "Product", action = "Details" }, constraints: new { productId = @"\d+" });
而在新版route中,就可以直接设置Product/{productId:int}了,约束条件遵守如下约定:
{parameter:constraint}
目前支持的约束如下:
约束 示例 说明required "Product/{ProductName:required}" 参数必选
alpha "Product/{ProductName:alpha}" 匹配字母,大小写不限
int "Product/{ProductId:int}" 匹配int类型
long "Product/{ProductId:long}" 匹配long类型
bool "Product/{ProductId:bool}" 匹配bool类型
double "Product/{ProductId:double}" 匹配double类型
float "Product/{ProductId:float}" 匹配float类型
guid "Product/{ProductId:guid}" 匹配guid类型
decimal "Product/{ProductId:decimal}" 匹配decimal类型
datetime "Search/{datetime:datetime}" 匹配datetime类型
composite "Product/{ProductId:composite}" 匹配composite类型
length "Product/{ProductName:length(5)}" 长度必须是5个字符
length "Product/{ProductName:length(5, 10)}" 长度在5-10个之间
maxlength "Product/{productId:maxlength(10)}" 最大长度为10
minlength "Product/{productId:minlength(3)}" 最小长度为3
min "Product/{ProductID:min(3)}" 大于等于3
max "Product/{ProductID:max(10)}" 小于等于10
range "Product/{ProductID:range(5, 10)}" 对应的数组在5-10之间
Regex "Product/{productId:regex(^\d{4}$)}" 符合指定的正则表达式
而对于可选参数,则值需要在约束类型后面加一个问号即可,示例如下:
routes.MapRoute( "Product", "Product/{productId:long?}", new { controller = "Product", action = "Details" });
如果参数是必填的,需要保留一个默认值的话,则可以按照如下示例进行设置:
routes.MapRoute( "Product", "Product/{productId:long=1000}", new { controller = "Product", action = "Details" });
通用Routing