Asp.Net Web API(三)

来源:http://www.cnblogs.com/yan7/archive/2017/11/02/7773146.html
-Advertisement-
Play Games

Routing Tables路由表 在Asp.Net Web API中,一個控制器就是一個處理HTTP請求的類,控制器的public方法就被叫做action方法或簡單的Action。當Web API接收到一個請求的時候,它將這個請求路由到一個Action。 註意:Web API的路由與Asp.Net ...


Routing Tables路由表

    在Asp.Net Web API中,一個控制器就是一個處理HTTP請求的類,控制器的public方法就被叫做action方法或簡單的Action。當Web API接收到一個請求的時候,它將這個請求路由到一個Action。

        註意:Web API的路由與Asp.Net MVC的路由是非常相似的。主要區別就是Web API使用的是HTTP方法,而不是URI路徑來選擇Action

   為了確定哪個Action被調用,這個框架使用了一個註冊表。Visual Studio的Web API的項目模板會創建一個預設路由:

1   config.Routes.MapHttpRoute(
2                 name: "DefaultApi",
3                 routeTemplate: "api/{controller}/{id}",
4                 defaults: new { id = RouteParameter.Optional }
5 );

這個路由是在WebApiConfig文件中定義的,該文件位於App_Start目錄

  當Web API框架接收到一個HTTP請求時,它會試圖根據路由表中的一個路由模板來匹配其URI。如果無路由匹配,客戶端會接收到一個404(未找到)錯誤。例如,以下URI與這個預設路由的匹配

  • /api/product
  • /api/product/1
  • /api/product?category=category

然而,以下URI就不匹配,因為它缺少“api”欄位

  • /product/1     

        註意:在路由中使用“api”的原因是為了避免與ASP.NET MVC的路由衝突。通過這種方式,可以用“/product”進入一個控制器,而“/api/product”進入一個Web API控制器。當然,如果你不喜歡這種約定,也可以修改這個預設路由表。

     一旦一個匹配的路由被髮現,Web API便會選擇相應的Controller和Action。

         1.為了找到Controller,Web API會把“控制器”加到{Controller}變數的值

         2.為了找到Action,Web API會查找HTTP方法,然後尋找一個名稱以HTTP方法名開頭的方法。例如:對於Get請求,Web API會查找一個以“Get..”開頭的Action,這種約定只應用於GET,POST,PUT,DELETE方法,通過在Controller上使用attribute,你可以啟動其它的HTTP方法

         3.路由模板中其它的占位變數;例如{id},將會被映射成Action的參數。

Routing Variations路由變化

      HTTP方法

      替代使用HTTP方法的命名約定,你可以明確的為一個Action指定HTTP方法,通過以HttpGet,HttpPost,HttpPut或者HttpDelete屬性來對Action方法進行修身

      在下列示例中,FindProduct方法被映射到GET請求

1 [HttpGet]
2 public Product FindProduct(int id)
3 {
4    return repository.Get(id);
5 }

使用上面代碼時需要先註釋上面寫的GetProduct(int id);

因為如果不註釋 Web API會匹配到請求匹配的多個操作錯誤

Web API允許一個Action對應多個HTTP方法;

 1 [AcceptVerbs("GET","POST","HEAD")]
 2 public Product FindProduct(int id)
 3 {
 4     return repository.Get(id);
 5 }
 6 [AcceptVerbs("MKCOL")]
 7 public void MakeCollection()
 8 {
 9 
10 }

    第一個方法:指示該Action接收HTTP的GET,POST和HEAD方法。

    第二個方法:WebDAV方法,(基於Web的分散式著作與版本控制的HTTP方法,是一個擴展的HTTP方法,MKCOL時隸屬於WebDAV的一個方法,它在URI指定的位置創建集合)

通過Action名稱路由

   在預設的路由模板中,這個Web API使用HTTP方法去選擇Action。然而,你也可以在URI中創建包含Action名的路由

1 config.Routes.MapHttpRoute(
2           name: "DefaultApi",
3           routeTemplate: "api/{controller}/{Action}/{id}",
4           defaults: new { id = RouteParameter.Optional }
5 );

在這個路由模板中,{action}參數命名了控制器的Action方法。採用這種風格,需要使用註解屬性來指明所允許的HTTP方法。例如,假設你的控制器已有以下方法:

1 [HttpGet] 
2 public string Details(int id); 

  在這中情況下,一個GET請求“api/Product/Details/1”將會映射到這個Detail方法。這種風格的路由類似於Asp.Net MVC,而且可能與RPC式的API接近。

  你也可以通過使用ActionName註解屬性來覆蓋動作名。在以下例子中,有兩個Action映射到"api/product/thumbnail/id"。一個支持GET,一個支持POST

1 [HttpGet]
2 [ActionName("Thumbnail")]
3 public HttpResponseMessage GetThumbnailImage(int id);
4 [HttpPost]
5 [ActionName("Thumbnail")]
6 public void AddThumbnailImage(int id); 

NonActions

為了防止一個方法被當作Action所請求,可以使用NonAction註解屬性。它對框架發送信號:這個方法不是以一個Action,即使它可能與路由規則匹配

1 [NonAction]
2 public void IsNoAction();

Route Templates

   路由模板看起來類似一個URI路徑,但它可以具有占位符,並用{}來指示:

"api/{controller}/public/{category}/{id}"

當創建一個路由的時候,你可以為某些或所有占位符提供預設值

defaults: new { category = "all" }

你可以提供約束,它限制URI片段如何與占位符匹配

constraints: new { id = @"\d+" }   // 只有在“id”是一個或多個數字時才匹配

  上面語句是通過正則表達式來限製片段的取值,上面的註釋說明id片段只匹配一個或多個數字,因此URI中id片段必須是一個數字才能與這個路由進行匹配。

 

  這個框架試圖把URI路徑中的片段與這個模板進行匹配。模板中文字必須嚴格匹配。一個占位符可以匹配任何值,除非你指定了約束。這個框架不會URI另外的部分,例如主機名或者一個查詢字元串。這個框架會選擇路由表中第一個匹配的路由。

   這個有兩個特殊的占位符:“{Controller}”和“{Action}”。

       {Controller}提供控制器名

       {Action} 提供動作名。在Web API中,通常的約定是忽略{Action}的。

 

Defaults(預設值)

  如果你提供預設值,那麼這個路由匹配缺少這些片段的URI。例如

1 routes.MapHttpRoute(
2     name: "DefaultApi", 
3     routeTemplate: "api/{controller}/{category}", 
4     defaults: new { category = "all" } 
5 );

       這個URI“http://localhost/api/products”與這個路由是匹配的。“{category}”片段將賦成了預設值“all”。

 Route Dictionary(路由欄位)

     如果這個框架發現了一個匹配的URI,它會創建包含每個占位符值的字典。這個鍵值是不帶{}的占位符名稱。這個值取自於URI路徑或是預設值。這個欄位被存在IHttpRouteData對象中。在匹配路由階段,這個特殊的{Controller}和{Action}占位符的處理和其它占位符是一樣的,它們用另外的值被簡單的存儲在字典中。

      在預設值中可以使用特殊的RouteParameter.Optional值。如果一個占位符被賦予了這個值,那麼這個值將不會被添加到字典中,例如

1 routes.MapHttpRoute( 
2     name: "DefaultApi", 
3     routeTemplate: "api/{controller}/{category}/{id}", 
4     defaults: new { category = "all", id = RouteParameter.Optional } 
5 );

對於URI路徑“api/product”,路由字典將含有:controller:"product",category:"all"

然而,對於”api/product/toys/123“,路由字典將含有:controller:"product",category:"toys"

 

這個預設值也可以包含未出現的路由模板中的值。若這條路由匹配,則該值會被存儲在路由字典中。例如

1 routes.MapHttpRoute( 
2     name: "Root", 
3     routeTemplate: "api/root/{id}", 
4     defaults: new { controller = "product", id = RouteParameter.Optional } 
5 );

如果URI路徑是”api/root/7“,字典中將含有兩個值:controller:"product",id:"8"。

Selecting a Controller

     控制器選擇是由IHttpControllerSelector.SelectController方法來處理的。這個方法以HttpRequestMessage實例為參數。並返回HttpControllerDescriptor

     其預設實現是由DefaultHttpControllerSelector類提供的。這個類使用了一種很直接的演算法:

           1.查找路由字典的”controller“鍵。

           2.取得這個鍵的值,並附加字元串”Controller“,以得到控制器的類型名。

           3.用這個類型名查找Web API控制器

     例如,如果路由字典的鍵-值對為”controller“=”product“,那麼控制器類型便為”ProductController“。如果沒有匹配,或多個匹配,Web API框架會給客戶端返回一個錯誤。

   對於步驟3,DefaultHttpControllerSelector使用IHttpControllerTypeResolver介面以獲得Web API控制類型的列表。IHttpControllerTypeResolver的預設實現會返回所有符合以下條件的public類:

  1.  實現IHttpController的類
  2. 是非抽象類
  3. 名稱以”Contoller“結尾的類

Action Selection

      選擇了控制器後,Web API框架會通過調用IHttpActionSelector.SelectAction方法來選擇Action。這個方法以HttpControllerContext為參數,並返回HttpActionDescriptor。

      這個預設實現是由ApiControllerActionSelector類提供的。為了選擇一個Action,會查找以下方面: 

  1. HTTP請求的方法
  2. 這個路由模板的action占位符
  3. 控制器中Action的參數

      在查找選擇演算法之前,我們需要理解控制器Action的一些事情

          控制器的哪些方法被看成為Action?當選擇一個Action時,這個框架只考察控制器的public實例方法。而且,它會排除特殊名稱的方法(構造器,事件,操作符,重載符等),以及集成自ApiController的類方法

HTTP Methods

    Web API框架只會選擇與請求的HTTP方法匹配的Action,確定如下

  1. 你可以用註解屬性AcceptVerbs,HttpDelete,HttpGet,HttpPost,HttpOptions,HttpPatch,HttpPost或者HttpPut來指定HTTP方法
  2. 如果控制器方法名稱以Get,Post,Put,Delete,Head,Options或Patch開頭,那麼根據這個約定,該Action將支持相應的HTTP方法。
  3. 如果以上都不是,那麼這個方法將只支持Post請求。

Parameter Bindings

    參數綁定是指Web API如何創建參數值。以下是參數綁定的預設規則:

         1.簡單類型取自URI

         2.複雜類型取自請求正文

    簡單類型包括所有".NET框架簡單類型",另外還有,DateTime,Decimal,Guid,String和TimeSpan。對於每一個Action,最多只有一個參數可以讀取請求正文。

   在這種背景下,Action選擇演算法如下

  1. 創建該控制器中與HTTP請求方法匹配的所有Action的列表
  2. 如果路由字典有Action條目,移除與該條目值不匹配的Action
  3. 試圖將Action參數與該URI匹配,如下       

              a:針對每個Action,獲得簡單類型的參數列表,這是綁定得到URI參數的地方。該列表不包括可選參數

              b:從這個列表中,試著在路由字典或是在URI查詢字元串中,找到每個參數的匹配。匹配是與大小寫無關的,且與參數順序無關

              c:選擇這樣的一個Action,在列表中的每個參數在URI中有一個匹配

              d:如果滿足這些條件的Action不止一個,選用參數匹配最多的一個。

         4.忽略用[NonAction]註解屬性標註的Action。

    第3步可能會rang人困擾。其基本思想是,可以從URI,或請求體,或一個自定義綁定來獲取參數值。對於來自URI的參數,我們希望確保URI在其路徑(通過路由字典)或查詢字元串中實際包含一個用於此參數的值。

   例如,考慮以下Action

public void Get(int id)

   其id綁定到URI。因此,這個Action只能匹配在路由字典或查詢字元串包含了id值的URI

   可選參數是一個例外,因為它們是可選的。對於可選參數,如果綁定不能通過URI獲取它的值,是沒關係的。

   複雜類型是另一個原因的例外。一個複雜類型只能通過自定義綁定來綁定到URI。但是在這種情況下,Web API框架不能提前知道是否這個參數被綁定到一個特殊的URI。為了查明情況,這個框架需要調用這個綁定。選擇演算法的目的是在調用綁定之前根據靜態描述來選擇一個Action。因此,負責類型是屬於匹配演算法之外的。

    Action選擇之後,會調用所有參數綁定。

Summary:

  1.  Action必須匹配請求的HTTP方法。
  2. Action名必須匹配路由字典中的Action條目,如果有的話。
  3. 對於Action的各個參數,如果參數來自URI,那麼該參數名必須在路由字典或URI查詢字元串中能夠被找到(可選參數和複雜參數類型除外)
  4. 試圖匹配最多數目的參數。最佳匹配可能是一個無參數的方法。

Extended Points

        Web API為路由過程的某些部分提供了擴展點。

要為以上任一介面提供自己的實現,可使用HttpConfiguration對象的Services集合:

var config = GlobalConfiguration.Configuration;
config.Services.Replace(typeof(IHttpControllerSelector), new MyControllerSelector(config));

 

         


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

-Advertisement-
Play Games
更多相關文章
  • 在前面介紹了框架中工作流的幾個開發過程,本篇隨筆重點介紹一下日常審批環節中的具體處理過程,從開始創建表單,以及各個審批、會簽過程的流轉過程,希望大家對其中流程的處理有一個大概的印象。 ...
  • 本文實例講述了C#對圖片文件的壓縮、裁剪操作方法,在C#項目開發中非常有實用價值。分享給大家供大家參考。具體如下: 一般在做項目時,對圖片的處理,以前都採用在上傳時,限制其大小的方式,這樣帶來諸多不便。畢竟網站運維人員不一定會對圖片做處理,經常超出大小限制,即使會使用圖片處理軟體的,也由於個人水平方 ...
  • 劇情介紹 在傳統的信息系統(比如小規模的ERP\MES系統),往往只是進行簡單的應用伺服器和資料庫伺服器的分散式部署,以此來提高應用系統的負載能力,而伴隨著訪問的增大,應用伺服器層面除了做硬體和網路的擴容,很難應對【套路式開頭】。 當然現在開源技術很多,不就是分散式麽,應用伺服器分散式、資料庫讀寫分 ...
  • 在現代Web應用程式中,通常會使用Web, WebApp, NativeApp等多種呈現方式,而後端也由以前的Razor渲染HTML,轉變為Stateless的RESTFulAPI,因此,我們需要一種標準的,通用的,無狀態的,與語言無關的認證方式,也就是本文要介紹的 JwtBearer 認證。 目錄 ...
  • 從java培訓出來,進了一家企業,需要.net開發,就開始了一無所知的net世界!從oracle開始著手,一步步接觸,發現和java有不少類似的知識點。波瀾不驚的渡過了一個月,問題來了,讓小菜開始學習企業框架了。直接丟過來一個框架項目,好奇心突起,想對浩瀚的知識海洋進行探究,探究到後來,發覺懵逼了! ...
  • is檢查對象是否相容與指定類型,返回Boolean值true或者false,值得註意的是,在使用is進行類型轉換的時候是永遠不會拋出異常的,例如: object o=new Object(); Boolean a=(o is object); //返回a=true Boolean b=(o is E ...
  • HttpResponseException HTTP響應異常 如果Web API控制器拋出一個未捕捉的異常,會發生什麼呢?在預設情況下,大多數異常都會轉換為一個帶有狀態碼500的內部伺服器錯誤的HTTP響應。 這個HTTPResponseException類型是一個特殊的類型。這種異常會返回你在異常 ...
  • 1.razor: 2.aspx: ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...