asp.net core 3.x Endpoint終結點路由1-基本介紹和使用

来源:https://www.cnblogs.com/jionsoft/archive/2019/12/29/12115417.html
-Advertisement-
Play Games

前言 我是從.net 4.5直接跳到.net core 3.x的,感覺asp.net這套東西最初是從4.5中的owin形成的。目前官方文檔重點是講路由,沒有特別說明與傳統路由的區別,本篇主要介紹終結點路由的相關概念和如何使用,不會詳細介紹路由,這個參考官方文檔就ok了。如果將來有機會研究到底層再深度 ...


前言

我是從.net 4.5直接跳到.net core 3.x的,感覺asp.net這套東西最初是從4.5中的owin形成的。
目前官方文檔重點是講路由,沒有特別說明與傳統路由的區別,本篇主要介紹終結點路由的相關概念和如何使用,不會詳細介紹路由,這個參考官方文檔就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時,服務端是存在a.aspx這個文件的,服務端根據此文件幫我們創建一個對應類的實例處理請求。
後來需求越來越複雜,出現了路由,目的是將請求地址與執行請求的處理器的直接關聯,變成映射關聯,映射規則由我們自己配置。
在asp.net core 3.x之前這個路由系統是包含在mvc內部的,.net framework時代有個特殊的HttpModule來實現mvc,路由系統也包含其中。.net core是由有個特殊的中間件來實現mvc的,路由系統就包含在這個中間件中。
這種方式有個問題,mvc只是一個中間件,路由系統包含在其中,如果我們希望在mvc中間件之後加入其它中間件,其它中間件是無法(也許是不方便)訪問路由相關信息的。
另外asp.net core並不是只有mvc,還有webapi、blazor、signlR、接入gRpc等,將來還有更多,我們的路由系統能否提出來,讓所有框架都可以用?

因此出現了終結點路由,我們說路由的根本目的是將用戶請求地址,映射為一個請求處理器,最簡單的請求處理器可以是一個委托 Func<HttpCotnext,Task>,也可以是mvc/webapi中某個controller的某個action,所以從抽象的角度講 一個終結點 就是一個處理請求的委托。由於mvc中action上還有很多attribute,因此我們的終結點還應該提供一個集合,用來存儲與此請求處理委托的關聯數據。
從抽象的角度可以簡單理解為   一個終結點 = 處理請求的委托 + 與之關聯的附加(元)數據。對應到mvc來理解的話 終結點 = action + 應用其上的attribute集合。但記住終結點是個抽象的概念,並不只服務於mvc,原理大概如下:

  1. 在程式啟動前我們應該定義好程式中有哪些終結點,當然不是我們手動一個個定義,而是根據目標框架自動生成,針對mvc來說的話可以自動將程式中與路由匹配的action轉換成對應的終結點,其它框架應該也有對應的方式,反正最終我們所有用來處理請求的東東都變成了終結點。這步是在定義路由時自動完成的
  2. 除了定義終結點我們還要定義 請求路徑 與 終結點的對應關係,將來請求抵達時才能匹配找到合適的終結點來處理我們的請求,這步相當於定義路由
  3. 我們還需要定義一個解析器,當請求抵達時根據終結點與路徑的對應關係找到終結點,微軟已定義好對應的中間件來表示這個解析器。
  4. 最後我們需要定義一個中間件,在上面的中間件執行後 我們可以拿到與當前請求匹配的終結點,最終調用它的委托處理請求,這個中間件就是mvc中間件
  5. 到此asp.net core 3.x的中間件路由預設差不多就這樣了,此時我們可以定義自己的中間件,放在步驟3後面,拿到終結點做一些高級處理。微軟定義的一些中間件也是這個套路

如何使用

在通過vs預設模板創建asp.net core 3.x項目時,在startup中會看到這樣的代碼

1 app.UseRouting();
2 app.UseEndpoints(endpoints => {
3   endpoints.MapControllerRoute(
4     name: "default",
5     pattern: "{controller=Home}/{action=Index}/{id?}");
6 });

註冊路由

看代碼的第2行。它有如下3個任務

  1. 創建終結點定義,針對mvc來說會自動將程式中與路由格式匹配上的action轉換為終結點。在第5行之後可以調試觀察endpoints.DataSource屬性,生成好的終結點就在裡面
  2. 建立url與終結點的對應關係,這種關係存在哪?我也不曉得
  3. 註冊mvc中間件(它在將來請求抵達,且之前有中間件解析得到與當前請求匹配的終結點後,開始mvc旅程)

這裡路由跟以前的寫法差不多,上面預設值啊、約束啊就去看官方文檔吧。
創建終結點也會參照屬性路由,微軟推薦webapi使用屬性路由,mvc使用傳統路由。你會看到創建預設webapi項目時這樣的 endpoints.MapControllers(); 

終結點進一步定製

預設情況下是根據定義的路由去找到匹配的action最後生成終結點,這個生成終結點的過程我們是可以參與的,具體辦法是通過endpoints.MapControllerRoute的返回對象上調用相關擴展方法,本質上是向終結點的創建過程加入一些委托,將來創建終結點時,這些委托將被調用,代碼如下:

1 endpoints.MapControllerRoute(
2                     name: "default",
3                     pattern: "{controller=Home}/{action=Index}/{id?}").Add(endpointBuilder=> {
4                         //通過endpointBuilder獲取與action關聯的數據,比如attribute和其它元數據
5                         //通過endpointBuilder插入我們向放進終結點的數據
6                     });

動態路由

app.UseEndpointsmvc時就說明瞭使用mvc和webapi了,預設情況下一個action會創建一個對應的終結點,請求抵達時匹配到終結點就直接執行了。但有時候我們希望自己控制一個請求過來時使用哪個controller的哪個action,具體做法:
定義一個類,繼承DynamicRouteValueTransformer,並註冊到ioc容器中,最後調用一個擴展方法,看代碼:

 1     class MyRouteValueTransformer : DynamicRouteValueTransformer
 2     {
 3         public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
 4         {
 5             //通過values可以拿到原始路由數據
 6             //可以替換或加入新的數據
 7             values.Add("controller", "jj");
 8             values.Add("action", "kkk");
 9             return new ValueTask<RouteValueDictionary>(values);
10         }
11     }
12 
13 public void ConfigureServices(IServiceCollection services)
14         {
15             services.AddSingleton<MyRouteValueTransformer>();
16             services.AddControllers();
17         }
18 
19 endpoints.MapDynamicControllerRoute<MyRouteValueTransformer>("aaa/bbb/{id}");

這樣將來請求抵達時,解析得到終結點時會調用我們的MyRouteValueTransformer,我們可以獲取已解析得到的路有數據,然後選擇替換/增加某些路由數據,從而達到定製化

 

回退路由

預設情況下請求抵達時,若沒有找到匹配的終結點,就直接404了,我們希望當沒有匹配到任何終結點時直接執行某個預設的終結點,可以用如下方式:

endpoints.MapFallbackToController("{controller}/{action}/{id?}", "kkk", "jj");

當請求抵達時,如果沒有匹配到任何終結點,則預設執行jjController.kkk方法。可以想象得到此功能可能是通過動態路由實現的

還有幾個相關的擴展方法,有了上面的講解,估計你也能猜出是幹嘛用的了。關於路由註冊就暫時說這麼多

 

自定義中間件提前拿到終結點數據

app.UseRouting();對應概述中的步驟3,此擴展方法內部會註冊一個中間件,將來請求抵達時它會幫我們找到與當前請求匹配的終結點並存儲在HttpContext中,且匹配過程中解析得到的路由數據在Request.RouteValues中。我們可以在它後面加入自己的中間件

1 app.UseRouting();
2 app.Use((conttext,next)=> {
3       var endpoint = conttext.GetEndpoint();//拿到終結點
4       var routeData = conttext.Request.RouteValues;//拿到路由數據
     //做些牛B的事
5 return next(); 6 });

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Python第五十一天 python2升級為python3 公司使用的生產環境系統是centos7,所以這裡以centos7系統為基礎,講解將python2升級為python3的方法 centos7系統預設已經安裝了python2.7,但是python2的生命周期到2020年1月1日就會終結,在這個 ...
  • 1.用於檢索敏感辭彙 # !/usr/bin/python # -*- coding:utf-8 -*- info = input('請輸入檢索內容:') li = ['蒼老師','東京熱'] for i in li: if i in info: info = info.replace(i,'*** ...
  • 《瘋狂Java講義(第4版)》是《瘋狂Java講義》的第4版,第4版保持了前3版系統、全面、講解淺顯、細緻的特性,全面新增介紹了Java 9的新特性。 《瘋狂Java講義(第4版)》深入介紹了Java編程的相關方面,《瘋狂Java講義(第4版)》內容覆蓋了Java的基本語法結構、Java的面向對象特 ...
  • 1.引言 上一篇博文關於淺拷貝和深拷貝 https://www.cnblogs.com/zhaoyixiang/p/12116203.html 我們瞭解到我們在淺拷貝時對帶指針的對象進行拷貝會出現記憶體泄漏,那C++是否可以實現像python,JAVA一樣引入垃圾回收機制,來靈活的來管理記憶體。 遺憾的 ...
  • 上一篇文章我們已經知道可以通過task.wait/task.WaitAny/task.WaitAll,等方法來實現等待一個tsak或者一組task的執行完畢,這一個方法都會阻塞主線程也就是這一些操作都是主流程的一個必然環節,但是我們在實際項目中,也還會遇到這樣的場景,那就是主流程根本不關心task的... ...
  • 時間如流水,只能流去不流回! 點贊再看,養成習慣,這是您給我創作的動力! 本文 Dotnet9 https://dotnet9.com 已收錄,站長樂於分享dotnet相關技術,比如Winform、WPF、ASP.NET Core、Xamarin.Forms等,亦有C++桌面相關的Qt Quick和 ...
  • 隨著.NET Core 3.1的發佈,國內2019 中國.NET開發者峰會在上海的成功舉辦。從技術採用生命周期的角度來說,隨著.NET Core 3.1的發佈,有越來越多的廠商開始採用.NET Core, .NET Core 正在跨越技術鴻溝。.NET Core 正是順應應用程式現代化,應用程式容器... ...
  • 在上一篇文章 abp(net core)+easyui+efcore實現倉儲管理系統——ABP WebAPI與EasyUI結合增刪改查之五(三十一) 中我們實現了新增組織部門信息功能,不過還存在一些BUG。今天我們來繼續完善組織部門信息新增功能,併進行測試。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...