WebApi-路由機制

来源:https://www.cnblogs.com/chenxinblogs/archive/2018/04/06/8728541.html
-Advertisement-
Play Games

一、WebApi路由機制是什麼? 路由機制通俗點來說:其實就是WebApi框架將用戶在瀏覽器中輸入的Url地址和路由表中的路由進行匹配,並根據最終匹配的路由去尋找並匹配相應的Controller和Action並執行的一個過程。 從WebApi框架接收到來自外部環境的介面調用請求到指定介面的執行大概需 ...


一、WebApi路由機制是什麼?

  路由機制通俗點來說:其實就是WebApi框架將用戶在瀏覽器中輸入的Url地址和路由表中的路由進行匹配,並根據最終匹配的路由去尋找並匹配相應的Controller和Action並執行的一個過程。

從WebApi框架接收到來自外部環境的介面調用請求到指定介面的執行大概需要以下的匹配過程:1、匹配URL路由 2、Controller匹配 3、Action匹配

下麵我麽分別對這幾個流程進行詳細說明。

 

二、匹配URL路由

  WebApi框架接收到來自外部的介面請求後,首先將路由表中的路由一條一條和Url地址進行匹配,一旦匹配上則不再繼續往下匹配,如果匹配完了所有路由都未匹配上,則會報404錯誤。

如果成功匹配上指定路由,則框架根據路由的Url模板中指定的Controller的所在位置以及Action的所在位置從用戶請求的Url中提取出將要調用的Controller的名稱以及Action的名稱,當然要被調用的Controller名或者Action名也可能不是從用戶發起的介面調用請求Url中獲得的,因為WebApi中在進行路由配置時提供了參數預設值的配置,也就是說Controller名或者Action名可能來源於路由配置時的預設值。

該流程結束後:WebApi框架將會從用戶請求的介面調用URL中提取出用戶想調用的介面所對應的Controller 、Action 、以及用戶傳給指定Action的參數(即路由數據)等等,

這些數據存儲在了一個字典集合中,這個路由數據字典我們可以在Action方法中通過如下方式獲得:

1 IHttpRouteData routeData = Request.GetRouteData();
2 IDictionary<string, object> routeDataValues = routeData.Values;

  這裡需要澄清的幾點的是:

1、URL未匹配上任何路由 和  匹配上了路由但是未找到相應的Controller和Action 是兩個不同的概念,IIS對這兩種情況的響應是不一樣的。

URL未匹配上路由:

  如果用戶請求的介面的地址不能和路由表中的所有路由相匹配,IIS將直接報告404錯誤。

匹配上了路由但未找到相應Controller或Action:

       如果匹配上了路由但是未找到響應的Controller或Action,那麼將報類似如下錯誤:

  MessageDetail節點詳細描述了是 Controller未找到還是 Action未找到。

2、由於路由表中可以配置一條或者多條路由,並且WebApi框架在匹配成功一條路由後將不再繼續往下匹配,也就是說即使此時後面還有路由可以

和當前請求匹配也不會被匹配到,所以請務必註意每條路由的配置順序,否則可能造成意想不到的結果。

如:

 1 public static void Register(HttpConfiguration config)
 2 {
 3             config.Routes.MapHttpRoute(
 4                 name: "TestRoute",
 5                 routeTemplate: "{controller}/{action}",
 6                 defaults: new { action = "Index" }
 7             );
 8             config.Routes.MapHttpRoute(
 9               name: "DefaultApi",
10               routeTemplate: "api/{controller}/{id}",
11               defaults: new { id = RouteParameter.Optional }
12             );
13 
14 }

假設我們此時代碼中包含如下控制器和Action:

 1 public class ValuesController : ApiController
 2 {
 3         public string Get()
 4         {
 5             return "value";
 6         }
 7         [HttpGet]
 8         public object QueryValues(int index)
 9         {
10             string[] strs = new string[] { "張三", "李四" };
11             if (index < 0 || index >= strs.Length)
12             {
13                 return JsonConvert.SerializeObject(strs);
14             }
15             return strs[index];
16         }
17 }

我們在瀏覽器中輸入:http://localhost:16982/api/Values,會發現總是匹配到的是TestRoute這個路由,實際上我們只是想訪問Values中的無參數的Get方法。

事實上,解決這個問題只需要將TestRoute路由的配置放到DefaultApi路由的後面即可。

三、Controller匹配

      經過路由匹配後,框架已經從用戶請求的Url中提取到需要訪問的Controller名、Action名、以及在路由模板中定義的參數所對應的值等等,此時WebApi框架從路由數據字典中獲取出鍵為:controller的值,在這個值的基礎上去找類型名為  Controller名+Controller 結尾的類,此時如果找到相應名稱的Controller類,則Controller匹配成功,但此時僅僅是Controller匹配成功,最終介面能否成功調用還需取決於下一個步驟中的Action匹配。

  Controller的匹配主要由介面:IHttpControllerSelector.SelectController方法來處理的,這個是WebApi框架定義的介面,定義如下:

1 public interface IHttpControllerSelector
2 {
3     // Methods
4     IDictionary<string, HttpControllerDescriptor> GetControllerMapping();
5     HttpControllerDescriptor SelectController(HttpRequestMessage request);
6 }

  WebApi框架對控制器的匹配進行了預設的實現,類名叫做:DefaultHttpControllerSelector,這個類預設實現了查找Controller的過程,在DefaultHttpControllerSelector內部通過 

IHttpControllerTypeResolver介面載入出所有的滿足條件的控制器類型,能被載入並查找的控制器類型必須滿足以下條件:

1、類必須是實現了IHttpController介面

2、必須是public

3、不能是abstract類

4、類名必須以Controller結尾

最終,從這些列表中找出名稱和路由數據中的Controller名同名的Controller類,並創建該類的實例對象。

當然如果我們需要有自己的控制器匹配的邏輯,我們也可以對其進行配置,通過在:/App_Start/WebApiConfig.cs類中進行配置,配置方式如下所示:

1     public static class WebApiConfig
2     {
3         public static void Register(HttpConfiguration config)
4         {
5             // 這裡我們配置成使用自己寫的匹配控制器的邏輯
6          GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new MyHttpControllerSelectory(GlobalConfiguration.Configuration));
7         }
8     }

雖然WebApi框架給我們提供了匹配控制器行為的擴展點,但是微軟的預設實現類DefaultHttpControllerSelector基本上可以滿足大多數場景了。

四、Action匹配

   路由機制找到了將要被調用的Controller類後,接下來就是在當前已經被匹配成功的控制器類下找一個合適的Action方法,並對其調用了,Action的具體匹配流程如下:

1、根據用戶調用介面時的請求方式(GET/POST/DELETE/PUT/Head等等)從已經匹配的控制器類中查找是用於該種請求方式的Action方法,通過該輪匹配可能會匹配出多個符合條件的Action方法。

2、如果路由數據字典中包含鍵為:action的值,那麼表示Action的名稱必須和該字典中的actionName相一致,也就是說只有Action方法的名稱和路由數據字典中的action名匹配的才算再次步驟匹配。(該步驟不一定是必須執行的,取決於被匹配的路由中是否有指定action占位符)

3、最後一步就是action的參數綁定了,action中的各個參數的值要麼來源於路由Url模板中定義好的參數在Url中提取到的值,要麼來源於QueryString(也就是?後面的參數值),當然這些說的只是.NET中的原生類型(包括:int/double/DateTime/TimeSpan/Guid等等)的綁定。並不包括自定義的複雜類型(如模型類),其實複雜類型的參數值的綁定預設實現方式是從請求報文提中獲得的。

Action的選擇由介面IHttpActionSelector.SelectAction()方法進行實現,WebApi框架對Action的匹配進行了預設的實現,預設實現類名為:ApiControllerActionSelector,

IHttpActionSelector介面定義如下:

1 public interface IHttpActionSelector
2 {
3     // Methods
4     ILookup<string, HttpActionDescriptor> GetActionMapping(HttpControllerDescriptor controllerDescriptor);
5     HttpActionDescriptor SelectAction(HttpControllerContext controllerContext);
6 }

  需要說明的是:能作為Action被執行的方法必須滿足以下幾點:

1、必須是public修飾的方法

2、未被[NonAction]特性修飾的方法

3、不是從ApiController類中繼承過來的方法

4、控制器的構造函數,等等也不會被匹配。

Action的匹配我們也可以實現自定義匹配規則,和上面提到的自定義Controller匹配規則的配置方式類似,如下:

1 public static void Register(HttpConfiguration config)
2 {
3    GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionSelector), new MyApiControllerActionSelector());
4
5 }

 

  本文主要講述了WebApi框架如何將來自用戶的介面調用請求映射到具體的Controller和Action,並對其進行執行的過程,最容易讓人困惑的部分或許還是Action的選擇部分,

後續我們將繼續討論關於Action選擇部分的具體細節以及參數綁定過程。

  


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

-Advertisement-
Play Games
更多相關文章
  • 1)File類操作文件的屬性 1.File類的常用方法 1. 文件的絕對完整路徑:getAbsolutePath() 文件名:getName() 文件相對路徑:getPath() 文件的上一級目錄:getParent() 文件的大小為:length() 刪除文件:delete() 具體操作請參考如下 ...
  • 持久化就是將記憶體中的數據保存起來,使之可以長期存在。 在Java中 可以做到持久化有很多種方法。 其中有: 1. 堵塞型IO,也就是我們經常說的io流; 2. 非堵塞型IO,通常稱為New IO。也就是我們經常說的nio 3. Xml 4. 序列化 5. 資料庫持久化 本人將在之後博客中開展關於Ja ...
  • 一、概述 很多程式都有記錄日誌的需求,並且日誌中包含的信息即有正常的程式訪問日誌,還可能有錯誤、警告等信息輸出,python的logging模塊提供了標準的日誌介面,你可以通過它存儲各種格式的日誌,logging的日誌可以分為 debug(), info(), warning(), error()  ...
  • Python的數據類型在前幾節我們都簡單的一一介紹了,接下來我們就要講到Python的控制判斷迴圈語句 在現實編程中,我們往往要利用電腦幫我們做大量重覆計算的工作,在這樣的情況下,需要機器能對某個條件進行判斷,或是對某個行為進行重覆操作 這時我們就必須要知道如何去編寫迴圈判斷語句 if... el ...
  • 1.安裝anaconda 下載地址:[清華鏡像站][url1] 針對自己的操作系統,在 下載鏈接 應用軟體 conda 中選擇合適版本。安裝過程較為簡單,這裡就不在詳細介紹。 需要註意 的是windows系統安裝過程中需要註意,勾選將軟體添加至windows路徑(也可以手動添加,即在環境變數 pat ...
  • 在項目中,遇到需求,需要進行規則入庫,想到使用正則進行表達式的拆分和分類,具體如下: 目標是:拆分介於表示邏輯運算的“And”或者“Or”的子句,比如:Operation Mode(Operation Mode_2) (Approve CR1) equals Accept;Need Physical ...
  • 題目描述 給定一個完全圖,保證$w_{u,v}=w_{v,u}$且$w_{u,u}=0$,等概率選取一個隨機生成樹,對於每一對$(u,v)$,求$dis(u,v)$的期望值對$998244353$取模。 輸入 第一行一個數$n$ 接下來$n$行,每行$n$個整數,第$i$行第$j$個整數表示$w_{ ...
  • 因為對錶達式樹有點興趣,出於練手的目的,試著寫了一個深拷貝的工具庫。支持.net standard2.0或.net framework4.5及以上。 GitHub地址https://github.com/blurhkh/DeepCopier nuget地址https://www.nuget.org/ ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...