在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" }); });}
第三步:分別創建如下如下三種
新聞熱點
疑難解答