dotnet core 开发体验之Routing
開始
回顧上一篇文章:dotnet core開發體驗之開始MVC?里面體驗了一把mvc,然后我們知道了aspnet mvc是靠Routing來驅動起來的,所以感覺需要研究一下Routing是什么鬼。
Routing簡單使用體驗
首先我們用命令yo aspnet創建一個新的空web項目。(Yeoman的使用自己研究,參考:https://docs.asp.net/en/latest/client-side/yeoman.html?#building-projects-with-yeoman)
創建完項目后,在project.json里面添加Routing依賴。
"dependencies": { ? ?..."Microsoft.AspNetCore.Routing": "1.0.0-*"},添加完依賴后,修改Startup里面的Configure,和ConfigureServices里面添加Routing的使用依賴
修改前:
修改后:
public void ConfigureServices(IServiceCollection services){services.AddRouting(); }public void Configure(IApplicationBuilder app){ ? ?
? ?var endpoint = new RouteHandler((c) => c.Response.WriteAsync("Hello, I am Routing!"));app.UseRouter(endpoint); }
dotnet run 然后瀏覽器訪問http://localhost:5000/ 顯示為Hello, I am Routing! 接下來我們在http://localhost:5000/ 后面加入一些其他的東西來訪問,發現其實還是一樣打印Hello, I am Routing! 這讓我們感覺好像并沒有什么卵用的樣子。不著急我們先來看看Routing是怎么運行起來的。在開始這話題之前需要先了解到什么是中間件,參考:https://docs.asp.net/en/latest/fundamentals/middleware.html
Routing的最基本運行原理
Routing的驅動入口就是基于middleware的。可以先看看?app.UseRouter(endpoint)的內部實現,參考一個擴展方法類RoutingBuilderExtensions,可以看到最后有一句代碼return builder.UseMiddleware<RouterMiddleware>(router)?。這里可以很明顯看到,入口在RouterMiddleware的Invoke方法。
? ?public async Task Invoke(HttpContext httpContext) ? { ? ?? ?? ?var context = new RouteContext(httpContext);context.RouteData.Routers.Add(_router); ? ? ?
? ?? ??await _router.RouteAsync(context); ? ? ?
? ?? ??if (context.Handler == null){_logger.RequestDidNotMatchRoutes(); ? ? ?
? ?? ??? ? ?await _next.Invoke(httpContext);} ? ? ?
? ?? ??else{httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature(){RouteData = context.RouteData,}; ? ? ? ? ? ?await context.Handler(context.HttpContext);}}
這個入口的實現是這樣的:
Invoke入口 ===>>> 實例化一個?RouteContext?===>>> 把我們傳進來的?IRouter?存到 RouteContext里面的?RouteData===>>> 再執行IRouter的RouteAsync方法把RouteContext對象傳進去提供給具體實現使用。===>>> 如果context.Handler沒有東西,就執行下一個RequestDelegate,如果有的話就把RouteData保存起來然后執行這個RequestDelegate。
看到了這里我們已經可以明白下面這個代碼運行起來的原理。
public void Configure(IApplicationBuilder app){ ? ?? ?var endpoint = new RouteHandler((c) => c.Response.WriteAsync("Hello, I am Routing!"));app.UseRouter(endpoint); }
可能還會有人不明白RouteHandler是個什么鬼,既然我們知道了代碼的實現運行原理,那么肯定可以猜到RouteHandler是有實現接口IRouter的。我們可以看RouteHandler代碼
? ?public Task RouteAsync(RouteContext context) ? ?{context.Handler = _requestDelegate; ? ?? ?? ?return TaskCache.CompletedTask;}
這里可以看到把我們的(c) => c.Response.WriteAsync("Hello, I am Routing!")賦值給context.Handler,然后由RouterMiddleware來執行我們這個事件方法。于是我們就可以在瀏覽器上面看到輸出 Hello, I am Routing!這么一句話了。
Routing的一些使用
文章到現在,我們雖然知道了Routing運行起來的一個大概原理,但是我們一直打印出相同內容,確實也沒有什么卵用呀。我們要改一下讓打印內容能有點改變。這個時候可以使用到Routing提供的Route類來使用。代碼修改如下:
? ?public void Configure(IApplicationBuilder app) ? ?{ ? ?? ? ? ?var endpoint = new RouteHandler((c) => c.Response.WriteAsync($"Hello, I am Routing! your item is {c.GetRouteValue("item")}")); ?
? ? ??var resolver = app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>(); ? ? ?
? ? ? ?var runRoute = new Route(endpoint,"{item}",resolver);app.UseRouter(runRoute);}
修改完代碼后,我們再次編譯運行,然后輸入http://localhost:5000/ 我們發現一片空白,然后再輸入http://localhost:5000/abc 發現打印出來的是Hello, I am Routing! your item is abc。然后再輸入其他的?http://localhost:5000/abc/cc?發現也是一片空白。這是因為我們給路由添加的匹配是主機地址/+{item}那其他的路徑都是匹配不到,那么肯定就是不會顯示任何東西啦。假設我們要給一個默認值,那么可以改成這樣
var runRoute = new Route(endpoint,"{item=home}",resolver);
OK,這個時候我們再輸入http://localhost:5000/ 看到的就是Hello, I am Routing! your item is home。
匹配原理相對比較復雜點,想要了解的話可以參考?RouteBase的源碼,然后看相關的類,看看我們設置的模板是如何解析的,然后如何和url進行匹配的。如果要要來解釋完整個過程的話,這個文章肯定是不夠的,所以各位可以自己了解一下。
假如要配置多個路由支持的話,可以使用RouteCollection
? ?public void Configure(IApplicationBuilder app) ? ?{ ? ? ?? ? ?var endpoint = new RouteHandler((c) => c.Response.WriteAsync($"Hello, I am Routing! your item is {c.GetRouteValue("item")}"));
? ? ?var resolver = app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>(); ? ? ?
? ? ?var runRoute = new Route(endpoint,"{item=home}",resolver); ?
? ? ?var otherRoute = new Route(endpoint,"other/{item=other_home}",resolver); ?
? ? ?var routeCollection = new RouteCollection();routeCollection.Add(runRoute);routeCollection.Add(otherRoute);app.UseRouter(routeCollection);}
修改成上面的代碼后就支持兩個路由,假如輸入的url是?http://localhost:5000/other?那么就是使用runRoute,如果輸入的是http://localhost:5000/other/myother 那么使用的就是otherRoute。
這樣書寫暴露了很多細節東西,我們可以用 Routing提供的RouteBuilder類來編寫相同的東西。代碼修改一下如下:
public void Configure(IApplicationBuilder app) ? ?{ ?? ? ?var endpoint = new RouteHandler((c) => c.Response.WriteAsync($"Hello, I am Routing! your item is {c.GetRouteValue("item")}")); ? ? ? ?var routeBuilder = new RouteBuilder(app){DefaultHandler = endpoint,};routeBuilder.MapRoute("default","{item=home}");routeBuilder.MapRoute("other","other/{item=other_home}");app.UseRouter(routeBuilder.Build());}
如果有一些特殊的的路由配置,我們也可以使用routeBuilder.Routes.Add(route);這代碼來添加。至于能配置的模板都有些什么,可以看 Routing 的 Template 的測試類:https://github.com/aspnet/Routing/tree/dev/test/Microsoft.AspNetCore.Routing.Tests/Template?看完基本就知道都有些什么樣的模板格式可以使用了。
實現自己的 RouteHandler
到現在,我們已經知道了Routing大概是怎么運行起來,知道了如何簡單的使用。那么接下來可以來創建一個自己的RouteHandler,來加深一下對Routing的使用體驗。
創建一個類MyRouteHandler,實現接口IRoute:
public class MyRouteHandler : IRouter {public VirtualPathData GetVirtualPath(VirtualPathContext context){ ? ? ? ?return null;}public Task RouteAsync(RouteContext context){context.Handler = (c) =>{var printStr = $"controller:{c.GetRouteValue("controller")}," +$"action:{c.GetRouteValue("action")},id:{c.GetRouteValue("id")}"; ? ? ? ? ? ?return c.Response.WriteAsync(printStr);}; ? ? ? ?return TaskCache.CompletedTask;} }然后我們的路由配置改成這樣:
? ?public void Configure(IApplicationBuilder app) ? ?{ ? ? ? ?var endpoint = new MyRouteHandler(); ? ? ? ?var routeBuilder = new RouteBuilder(app){DefaultHandler = endpoint,};routeBuilder.MapRoute("default","{controller=Home}/{action=Index}/{id?}");app.UseRouter(routeBuilder.Build());}然后打開瀏覽器http://localhost:5000/ 打印出來的內容是?controller:Home,action:Index,id:?。這樣是不是很像我們去調用mvc的控制器和控制器的行為呢?Routing的體驗文章到這來就結束了,謝謝觀看。
相關文章:
ASP.NET Core 1.0 入門——了解一個空項目
ASP.NET Core 1.0 部署 HTTPS (.NET Framework 4.5.1)
.NET Core 1.0、ASP.NET Core 1.0和EF Core 1.0簡介
云服務器下ASP.NET Core 1.0環境搭建(包含mono與coreclr)
使用VS Code開發ASP.NET Core 應用程序
dotnet run是如何啟動asp.net core站點的
ASP.NET Core提供模塊化Middleware組件
“dotnet restore"和"dotnet run"都做了些什么?
探秘 dotnet run 如何運行 .NET Core 應用程序
.NET Portability Analyzer 已開源
ASP.NET Core的配置(1):讀取配置信息
ASP.NET Core的配置(2):配置模型詳解
.NET Core 1.0 RC2 歷險之旅
使用VS Code開發 調試.NET Core 應用程序
讓我們Core在一起:ASP.NET Core & .NET Core
.NET Core VS Code 環境配置
官方博客明確了 .NET Core RC2/RTM 時間表
.NET Core全新的配置管理[共9篇]
利用記事本創建一個ASP.NET Core RC2 MVC應用
微軟.NET 正式劈腿成功,橫跨所有平臺
.NET Core 1.0 CentOS7 嘗試
解讀發布:.NET Core RC2 and .NET Core SDK Preview 1
[.NET Core].NET Core R2安裝及示例教程
ASP.NET Core 開發-中間件(Middleware)
結合Jexus + Kestrel 部署 asp.net core 生產環境
通過Jexus 部署 dotnetcore版本MusicStore 示例程序
ASP.NET Core 中文文檔 第一章 入門
用 Visual Studio Code 在 macOS 上創建首個 ASP.NET Core 應用程序
用 Visual Studio 和 ASP.NET Core MVC 創建首個 Web API
用 Visual Studio 發布一個 Azure 云 Web 應用程序
ASP.NET Core MVC 與 Visual Studio 入門
第二章指南(4.2)添加 Controller
DotNet Core 介紹
asp.net core 中間件詳解及項目實戰
教你實踐ASP.NET Core Authorization(免看文檔教程)
asp.net core 使用 Redis 和 Protobuf 進行 Session 緩存
asp.net core 中間件詳解及項目實戰
第二章 指南(4.3)添加 View
原文地址:http://www.cnblogs.com/caipeiyu/p/5597775.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的dotnet core 开发体验之Routing的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: asp.net core 中间件详解及项
- 下一篇: Visual Studio Code五月