在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框架是基于Middleware来实现的,这样就可以将其添加到HTTP的请求Pipeline中了,它可以喝其它任意Middleware一起进行组合使用,如静态文件处理程序、错误页、或者SignalR服务器。
在使用Routing框架之前,首要要了解Routing的作用,作用很简单:
路由系统的执行流程如下:
和之前的Routing系统有点不同的是,老版的Routing系统一旦成功匹配一个路由,就将其交由其对应的Handler,不管对应的Handler能不能处理该请求,所以就会出现route匹配成功了,但是找不到对应的action,此时就会出现404错误,而新版对此作出了上述第4步骤的改进(重新将控制权交回给Routing系统,进行重新匹配),看起来还是非常不错的。
在之前的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" });
关于示例使用,我们先不从MVC开始,而是先从普通的Routing使用方式开始,新版route添加的时候默认添加的是TemplateRoute
实例,并且在该实例实例化的时候要设置一个Handler
。
举例来说,我们先创建一个空的ASP.NET 5项目,并在project.json文件的dependencies节点中添加程序集"Microsoft.AspNet.Routing": "1.0.0-beta3"
,,在Startup.cs
的Configure
方法里添加如下代码:
public void Configure(IapplicationBuilder app){ RouteCollection routes = new RouteCollection(); routes.Add(new TemplateRoute(new DebuggerRouteHandler("RouteHandlerA"), "", null)); routes.Add(new TemplateRoute(new DebuggerRouteHandler("RouteHandlerB"), "test/{a}/{b:int}", null)); routes.Add(new TemplateRoute(new DebuggerRouteHandler("RouteHandlerC"), "test2", null)); app.UseRouter(routes); // 开启Routing功能}
在这里,我们设置HTTP请求处理的的Handler为DebuggerRouteHandler
,该类继承于IRouter
,实例代码如下:
public class DebuggerRouteHandler : IRouter{ private string _name; public DebuggerRouteHandler(string name) { _name = name; } public string GetVirtualPath(VirtualPathContext context) { throw new NotImplementedException(); } public async Task RouteAsync(RouteContext context) { var routeValues = string.Join("", context.RouteData.Values); var message = String.Format("{0} Values={1} ", _name, routeValues); await context.HttpContext.Response.WriteAsync(message); context.IsHandled = true; }}
上述类,继承IRouter
以后,必须实现一个RouteAsync
的方法,并且如果处理成功,则将IsHandled
设置为true
。
访问如下网址即可查看相应的结果:
正常:`http://localhost:5000/`正常:`http://localhost:5000/test/yyy/12`404 :`http://localhost:5000/test/yyy/s`正常:`http://localhost:5000/test2`404 :`http://localhost:5000/test3`
注意:
TemplateRoute
和DebuggerRouteHandler
都继承于IRouter
,是实现前面所述的不出现404错误(继续匹配下一个路由)的核心。
在MVC示例程序中,我们只需要配置在调用app.UseMVC
方法的时候,使用委托中的MapRoute
方法来定义各种route就可以了。在这里我们以空白项目为例,来看看MVC的route如何使用。
第一步:在project.json文件的dependencies节点中引用程序集"Microsoft.AspNet.Mvc": "6.0.0-beta3"
,第二部:添加MVC的Middleware,并使用MVC,然后添加一条默认的路由,代码如下:
public void ConfigureServices(IServiceCollection services){ services.AddMvc();}public void Configure(IApplicationBuilder app){ app.UseMvc(routeBuilder => { routeBuilder.MapRoute( name: "default", template: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); });}
第三步:分别创建如下如下三种
新闻热点
疑难解答