asp.net core 3.x Endpoint终结点路由1-基本介绍和使用
前言
我是從.net 4.5直接跳到.net core 3.x的,感覺asp.net這套東西最初是從4.5中的owin形成的。
目前官方文檔重點是講路由,沒有特別說明與傳統(tǒng)路由的區(qū)別,本篇主要介紹終結(jié)點路由的相關(guān)概念和如何使用,不會詳細介紹路由,這個參考官方文檔就ok了。如果將來有機會研究到底層再深度剖析。
參考:
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/routing?view=aspnetcore-3.1
https://q.cnblogs.com/q/113644/?
https://aregcode.com/blog/2019/dotnetcore-understanding-aspnet-endpoint-routing/
概述
最初我們訪問 http://www.abc.com/a.aspx時,服務(wù)端是存在a.aspx這個文件的,服務(wù)端根據(jù)此文件幫我們創(chuàng)建一個對應(yīng)類的實例處理請求。
后來需求越來越復(fù)雜,出現(xiàn)了路由,目的是將請求地址與執(zhí)行請求的處理器的直接關(guān)聯(lián),變成映射關(guān)聯(lián),映射規(guī)則由我們自己配置。
在asp.net core 3.x之前這個路由系統(tǒng)是包含在mvc內(nèi)部的,.net framework時代有個特殊的HttpModule來實現(xiàn)mvc,路由系統(tǒng)也包含其中。.net core是由有個特殊的中間件來實現(xiàn)mvc的,路由系統(tǒng)就包含在這個中間件中。
這種方式有個問題,mvc只是一個中間件,路由系統(tǒng)包含在其中,如果我們希望在mvc中間件之后加入其它中間件,其它中間件是無法(也許是不方便)訪問路由相關(guān)信息的。
另外asp.net core并不是只有mvc,還有webapi、blazor、signlR、接入gRpc等,將來還有更多,我們的路由系統(tǒng)能否提出來,讓所有框架都可以用?
因此出現(xiàn)了終結(jié)點路由,我們說路由的根本目的是將用戶請求地址,映射為一個請求處理器,最簡單的請求處理器可以是一個委托 Func<HttpCotnext,Task>,也可以是mvc/webapi中某個controller的某個action,所以從抽象的角度講 一個終結(jié)點 就是一個處理請求的委托。由于mvc中action上還有很多attribute,因此我們的終結(jié)點還應(yīng)該提供一個集合,用來存儲與此請求處理委托的關(guān)聯(lián)數(shù)據(jù)。
從抽象的角度可以簡單理解為? ?一個終結(jié)點 = 處理請求的委托 + 與之關(guān)聯(lián)的附加(元)數(shù)據(jù)。對應(yīng)到mvc來理解的話 終結(jié)點 = action + 應(yīng)用其上的attribute集合。但記住終結(jié)點是個抽象的概念,并不只服務(wù)于mvc,原理大概如下:
在程序啟動前我們應(yīng)該定義好程序中有哪些終結(jié)點,當(dāng)然不是我們手動一個個定義,而是根據(jù)目標框架自動生成,針對mvc來說的話可以自動將程序中與路由匹配的action轉(zhuǎn)換成對應(yīng)的終結(jié)點,其它框架應(yīng)該也有對應(yīng)的方式,反正最終我們所有用來處理請求的東東都變成了終結(jié)點。這步是在定義路由時自動完成的
除了定義終結(jié)點我們還要定義 請求路徑 與 終結(jié)點的對應(yīng)關(guān)系,將來請求抵達時才能匹配找到合適的終結(jié)點來處理我們的請求,這步相當(dāng)于定義路由
我們還需要定義一個解析器,當(dāng)請求抵達時根據(jù)終結(jié)點與路徑的對應(yīng)關(guān)系找到終結(jié)點,微軟已定義好對應(yīng)的中間件來表示這個解析器。
最后我們需要定義一個中間件,在上面的中間件執(zhí)行后 我們可以拿到與當(dāng)前請求匹配的終結(jié)點,最終調(diào)用它的委托處理請求,這個中間件就是mvc中間件
到此asp.net core 3.x的中間件路由默認差不多就這樣了,此時我們可以定義自己的中間件,放在步驟3后面,拿到終結(jié)點做一些高級處理。微軟定義的一些中間件也是這個套路
如何使用
在通過vs默認模板創(chuàng)建asp.net core 3.x項目時,在startup中會看到這樣的代碼
注冊路由
看代碼的第2行。它有如下3個任務(wù)
創(chuàng)建終結(jié)點定義,針對mvc來說會自動將程序中與路由格式匹配上的action轉(zhuǎn)換為終結(jié)點。在第5行之后可以調(diào)試觀察endpoints.DataSource屬性,生成好的終結(jié)點就在里面
建立url與終結(jié)點的對應(yīng)關(guān)系,這種關(guān)系存在哪?我也不曉得
注冊mvc中間件(它在將來請求抵達,且之前有中間件解析得到與當(dāng)前請求匹配的終結(jié)點后,開始mvc旅程)
這里路由跟以前的寫法差不多,上面默認值啊、約束啊就去看官方文檔吧。
創(chuàng)建終結(jié)點也會參照屬性路由,微軟推薦webapi使用屬性路由,mvc使用傳統(tǒng)路由。你會看到創(chuàng)建默認webapi項目時這樣的?endpoints.MapControllers();?
終結(jié)點進一步定制
默認情況下是根據(jù)定義的路由去找到匹配的action最后生成終結(jié)點,這個生成終結(jié)點的過程我們是可以參與的,具體辦法是通過endpoints.MapControllerRoute的返回對象上調(diào)用相關(guān)擴展方法,本質(zhì)上是向終結(jié)點的創(chuàng)建過程加入一些委托,將來創(chuàng)建終結(jié)點時,這些委托將被調(diào)用,代碼如下:
動態(tài)路由
app.UseEndpointsmvc時就說明了使用mvc和webapi了,默認情況下一個action會創(chuàng)建一個對應(yīng)的終結(jié)點,請求抵達時匹配到終結(jié)點就直接執(zhí)行了。但有時候我們希望自己控制一個請求過來時使用哪個controller的哪個action,具體做法:
定義一個類,繼承DynamicRouteValueTransformer,并注冊到ioc容器中,最后調(diào)用一個擴展方法,看代碼:
這樣將來請求抵達時,解析得到終結(jié)點時會調(diào)用我們的MyRouteValueTransformer,我們可以獲取已解析得到的路有數(shù)據(jù),然后選擇替換/增加某些路由數(shù)據(jù),從而達到定制化
?
回退路由
默認情況下請求抵達時,若沒有找到匹配的終結(jié)點,就直接404了,我們希望當(dāng)沒有匹配到任何終結(jié)點時直接執(zhí)行某個默認的終結(jié)點,可以用如下方式:
endpoints.MapFallbackToController("{controller}/{action}/{id?}", "kkk", "jj");當(dāng)請求抵達時,如果沒有匹配到任何終結(jié)點,則默認執(zhí)行jjController.kkk方法。可以想象得到此功能可能是通過動態(tài)路由實現(xiàn)的
還有幾個相關(guān)的擴展方法,有了上面的講解,估計你也能猜出是干嘛用的了。關(guān)于路由注冊就暫時說這么多
?
自定義中間件提前拿到終結(jié)點數(shù)據(jù)
app.UseRouting();對應(yīng)概述中的步驟3,此擴展方法內(nèi)部會注冊一個中間件,將來請求抵達時它會幫我們找到與當(dāng)前請求匹配的終結(jié)點并存儲在HttpContext中,且匹配過程中解析得到的路由數(shù)據(jù)在Request.RouteValues中。我們可以在它后面加入自己的中間件
總結(jié)
以上是生活随笔為你收集整理的asp.net core 3.x Endpoint终结点路由1-基本介绍和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NetCore 3.1 安装本地化中文
- 下一篇: ASP.NET Core跨平台技术内幕