ASP.NET Core 2.1 : 十五.圖解路由(2.1 or earler)

来源:https://www.cnblogs.com/FlyLolo/archive/2019/01/08/ASPNETCore2_15.html
-Advertisement-
Play Games

本文通過一張圖來看一下路由的配置以及請求處理的機制。(ASP.NET Core 系列目錄) 一、概述 路由主要有兩個主要功能: 這兩個功能看起來這兩個是相反的。 A.路由的配置 路由的兩個功能都離不開一個基本的操作:路由的基本配置。在Startup中預設通過 routes.MapRoute(name ...


本文通過一張圖來看一下路由的配置以及請求處理的機制。(ASP.NET Core 系列目錄

一、概述

路由主要有兩個主要功能:

  1. 將請求的URL與已定義的路由進行匹配,找到該URL對應的處理程式並傳入該請求進行處理。
  2. 根據已定義的路由生成URL

這兩個功能看起來這兩個是相反的。

A.路由的配置

路由的兩個功能都離不開一個基本的操作:路由的基本配置。在Startup中預設通過 routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}")定義,

當然我們還可以繼續 routes.MapRoute(。。。);  這樣就定義了一系列的路由匹配方式組成一個路由表,例如這樣:

app.UseMvc(routes =>
{
    routes.MapRoute(name: "test", template: "Hello");
    routes.MapRoute("flylolo/{code}/{name}", MyRouteHandler.Handler);
    routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
});

每一個MapRoute會生成一個Route,第二個MapRoute看起來有些特殊,我們可以傳入一個自定義的RequestDelegate(本例為MyRouteHandler.Handler)來處理“flylolo/{code}/{name}”這樣的請求,

    public static class MyRouteHandler
    {
        public static async Task Handler(HttpContext context)
        {
            await context.Response.WriteAsync("MyRouteHandler");
        }
    }

它會被封裝成一個RouteHandler(new RouteHandler(MyRouteHandler.Handler))賦值給Route的target屬性,而對於另外兩種沒有指定的,Route的target屬性預設會被指定為MvcRouteHandler ,如下圖:

B.Handler的選擇

當請求進入之後,根據此路由表對該URL進行逐一匹配,並將請求交給匹配到的路由的target(即MvcRouteHandler或RouteHandler),調用 _target.RouteAsync(context); ,在這個方法中,若是MvcRouteHandler會對請求的Controller和Action驗證,若驗證成功,則對context(是一個RouteContext)的Handler屬性賦值一個匿名方法;若是RouteHandler則會直接將其封裝的RequestDelegate(本例為MyRouteHandler.Handler)賦值給RouteContext.Handler.

C.請求處理

經過Handler的選擇後,若RouteContext.Handler不為空,則調用RouteContext.Handler(HttpContext)對請求進行處理。

D.其他

回想一下中間件,這個是不是和app.Map("/test", XXHandle)這樣配置中間件的方式有點像,當請求路徑是/test的時候,請求交由XXHandle處理,同樣是Map,對比著更容易理解。

下麵通過一張圖看一下路由配置和請求處理的流程。

二、流程及解析

 點擊看大圖

  為了方便查看,對幾個“重點對象”做了顏色標識(點擊圖片可以看大圖):

 

  1. 路由的初始化配置
  2. 一切從Startup開始,之前在中間件的文章中介紹過,一般是通過多個UseXXX的方式將多個中間件組成“請求處理管道”,而在這裡通過UseMvc方法進行配置,傳入routes.MapRoute(...)這樣的一個或多個配置。
      接下來會New一個

RouteBuilder

    ,顧名思義就是一個Route的創建者,通過調用傳進來的一個或多個routes.MapRoute()方法生成多個Route,並配置預設的Handler。
                var routes = new RouteBuilder(app)
                {
                    DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
                };

                configureRoutes(routes);//調用Startup中的routes.MapRoute(...)方法

 

          ①調用RouteBuilder的Build方法,生成一個RouteCollection

        public IRouter Build()
        {
            var routeCollection = new RouteCollection();

            foreach (var route in Routes)
            {
                routeCollection.Add(route);
            }

            return routeCollection;
        }

 

          ②RouteCollection實現IRouteCollection和IRouter介面,他是在Startup中的配置組成的集合。

          ③RouterMiddleWare就是專門用於進行路由處理的中間件,在此將RouteCollection作為中間件RouterMiddleWare的參數,並將這個中間件插入管道中。

    public class RouterMiddleware
    {
        private readonly IRouter _router; //就是RouteCollection

        public async Task Invoke(HttpContext httpContext);

    }

 

  2. 請求處理流程

        ④請求的處理流程在RouterMiddleWare的invoke()方法中。

      ⑤請求首先會被封裝成一個RouteContext,本質就是將httpContext、_router(也就是RouteCollection)包裝到一個對象里。

  var context = new RouteContext(httpContext);
  context.RouteData.Routers.Add(_router);
public class RouteContext
{
   private RouteData _routeData;
   public RequestDelegate Handler ;
   public HttpContext HttpContext;//簡單的賦值
   public RouteData RouteData;
}

          ⑥調用_router(也就是RouteCollection)的RouteAsync(context)方法,在其中遍歷每一個路由

          ⑦若與請求URL匹配,則將對應的Handler賦值給context.Handler。

        public async virtual Task RouteAsync(RouteContext context)
        {
            // 快照備份
            var snapshot = context.RouteData.PushState(null, values: null, dataTokens: null);
            //遍歷
            for (var i = 0; i < Count; i++)
            {
                var route = this[i];
                context.RouteData.Routers.Add(route);

                try
                {
                    await route.RouteAsync(context);//若匹配,則給context.Handler賦值

                    if (context.Handler != null)
                    {
                        break;
                    }
                }
                finally
                {
                    if (context.Handler == null)
                    {
                        snapshot.Restore();//通過快照還原
                    }
                }
            }
        }

              ⑧在RouterMiddleWare的invoke()方法中,調用新賦值的context.Handler處理HttpContext;

httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature()
{
    RouteData = context.RouteData,
};

await context.Handler(context.HttpContext);

 三、其他

      由於文章寫的比較早各種原因一直沒有寫完,現在發現2.2版本之後,啟用了新的路由方案,還是把這章完成了發出來,有願意看的可以參考一下,下一篇文章介紹一下2.2版的新的路由方案,至於通過路由生成URL部分,就暫時不寫了。


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

-Advertisement-
Play Games
更多相關文章
  • 一.socketserver模塊 1.sockeserver的源碼流程 2.簡單的使用 socketserver服務端 socket客戶端 二.連接的合法性驗證 1.os.urandom(n)加密 os.urandom(n)是一種bytes類型的隨機生成n個位元組字元串,而且每次生成的值都不相同,再加 ...
  • 一、編寫一個簡單程式,要求數組長度為5,分別賦值10,20,30,40,50,在控制台輸出該數組的值。 package com.test; public class t01 { public static void main(String[] args) { // 靜態初始化 int i[] = n ...
  • 前言: 由於導師在我的畢設項目裡加了消息系統(本來想水水就過的..),沒辦法...來稍微研究研究吧..簡單簡單... 需求分析 我的畢設是一個博客系統 ,類似於簡書這樣的,所以消息系統也類似,在用戶的消息里包含了有:喜歡和贊、評論、關註、私信這樣的一類東西,這樣的一個系統應該包含以下的功能: 1. ...
  • 由於 Apache公司發現myBatis的分頁弊端,所以又研發出得補丁:PageHelper 中央倉庫5.1.2版連接地址: <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --><dependency ...
  • 變數 什麼是變數 變數就是變化的量,變就是變化,量用於衡量描述對象的狀態 為什麼要有變數 程式執行的本質就是一系列狀態的變化,變是程式執行的直接體現,所以我們需要有一種機制能夠反映或者說是保存下來程式執行時狀態以及狀態的變化。 變數的定義規範 #1.變數名只能是字母、數字或下劃線的組合 #2.變數名 ...
  • 寫在前面 從今天開始的幾篇文章,我將就國內目前比較主流的一些線上學習平臺數據進行抓取,如果時間充足的情況下,會對他們進行一些簡單的分析,好了,平臺大概有 ,`CSDN學院 網易雲課堂 慕課網 mongodb`裡面,如果對上述平臺造成了困擾,請見諒,畢竟我就抓取那麼一小會的時間,不會對伺服器有任何影響 ...
  • Django 系列博客(三) 前言 本篇博客介紹 django 的前後端交互及如何處理 get 請求和 post 請求。 get 請求 get請求是單純的請求一個頁面資源,一般不建議進行賬號信息的傳輸。 配置路由 配置視圖 配置頁面資源 post 請求 配置路由 配置視圖 配置頁面資源 前後端交互 ...
  • Kubernetes簡介 Kubernetes是Google基於Borg開源的容器編排調度引擎,作為CNCF(Cloud Native Computing Foundation)最重要的組件之一,它的目標不僅僅是一個編排系統,而是提供一個規範,可以讓你來描述集群的架構,定義服務的最終狀態,Kuber ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...