使用 ASP.NET Core MVC 建立 Web API——響應資料的內容協商(七)

DotNet菜園發表於2019-05-14

使用 ASP.NET Core MVC 建立 Web API

使用 ASP.NET Core MVC 建立 Web API(一)

使用 ASP.NET Core MVC 建立 Web API(二)

 使用 ASP.NET Core MVC 建立 Web API(三)

使用 ASP.NET Core MVC 建立 Web API(四)

使用 ASP.NET Core MVC 建立 Web API(五)

使用 ASP.NET Core MVC 建立 Web API(六)

 

     ASP.NET Core MVC 包含對通過固定格式或根據客戶端規範來設定響應資料格式的內建支援。

     ASP.NET Web API的內容協商(Content Negotiation)機制的理想情況是這樣的:客戶端在請求頭的Accept欄位中指定什麼樣的MIME型別,Web API服務端就返回對應的MIME型別的內容(響應頭的中Content-Type就是Accept中指定的MIME型別)。而現實情況是,Web API服務端能返回什麼MIME型別的響應型別取決於有沒有對應這個MIME型別的MediaTypeFormatter。ASP.NET Core Web API的預設提供JsonMediaTypeFormatter,如果要支援 XmlMediaTypeFormatter需要進行配置。

      ASP.NET Core MVC 使用的預設格式是 JSON。 內容協商由 ObjectResult 實現。 它還內建於從幫助程式方法(全部基於 ObjectResult)返回的特定於狀態程式碼的操作結果中。 還可以返回一個模型型別(已定義為資料傳輸型別的類),框架將自動將其打包在 ObjectResult 中。

      以下操作方法返回一個物件例項和 NotFound 幫助程式方法:     

[HttpGet("{id}")]
        public async Task<ActionResult<Book>> GetBookItem(int id)
        {
            var bookItem = await _context.Book.FindAsync(id); 

            if (bookItem == null)
            {
                return NotFound();
            }
            return bookItem;
        }

    將返回 JSON 格式的響應,除非請求了另一個格式且伺服器可以返回所請求格式。 可以使用 Rester工具建立包括 Accept 標頭的請求並指定另一種格式。 在此情況下,如果伺服器有可以生成所請求格式的響應的格式化程式,則結果會以伺服器首選的格式返回。

    1) 在Visual Studio 2017中按F5,啟動BookApi應用程式。

    2) 開啟Firefox瀏覽器,並開啟 Rester,在Reseter中,將 HTTP 方法設定為 GET

   3) 然後在URL輸入框中輸入要獲取的物件URI,例如 http://localhost:5000/api/book/25

   4) 選擇“Headers”選項卡,選擇“Accept”選項,並將值設定為 JSON (application/json)。

    5) 使用滑鼠點選“Send”按鈕。請求將收到具有作書籍資料的“200 正常”響應。如下圖。

 

     6) 選擇“Headers”選項卡,選擇“Accept”選項,並將值設定為 xml (application/xml)。

     7) 使用滑鼠點選“Send”按鈕。請求將收到具有作書籍資料的“200 正常”響應。如下圖。我們雖然指定 Accept為 application/xml,但是在預設情況下,ASP.NET Core MVC 僅支援 JSON。所以,即使指定另一種格式,返回的結果仍然是 JSON 格式,而不是我們希望的xml。如下圖。

 

      控制器操作可以返回 POCO(普通舊 CLR 物件),在這種情況下,ASP.NET Core MVC 將自動建立打包物件的 ObjectResult。 客戶端將獲取設有格式的序列化物件(預設為 JSON 格式,可以配置 XML 或其他格式)。 如果返回的物件為 null,那麼框架將返回 204 No Content 響應。

    1) 在Visual Studio 2017中開啟BookController.cs檔案,新增以下 GetBook 方法返回實體物件,程式碼如下:

[HttpGet("{id}")]
        public  Book GetBook(int id)
        {
            var bookItem =  _context.Book.Find(id);       
            return bookItem;
        }

     2)在Visual Studio 2017中按F5啟動Web應用程式。

    3) 開啟瀏覽器,一併開啟Rester。

     4) 將 HTTP 方法設定為 GET。將請求 URL 設定為 http://localhost:5000/api/Book/25

    5) 使用滑鼠點選“Send”按鈕。請求將收到具有作書籍資料的“200 正常”響應。如下圖。

   6) 請求無效將收到“204 無內容”響應。 如下圖。

 

    配置格式化程式

       如果應用程式需要支援預設 JSON 格式以外的其他格式,那麼可以新增 NuGet 包並配置 MVC 來支援它們。輸入和輸出的格式化程式不同。輸入格式化程式由模型繫結使用;輸出格式化程式用來設定響應格式。 還可以配置自定義格式化程式。請求頭的Accept中除非指定為application/xml或者application/json,否則指定其它任何MIME,

      新增 XML 格式支援

      在Visual Studio 2017若要新增對 XML 格式的支援,請安裝 Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet 包。

     1. 在Visual Studio 2017的選單>工具>選項對話方塊中,選擇“NuGet包管理器”中的常規,根據自己需要,設定預設包管理格式,如下圖。

     2. 在解決方案資源管理器中,右鍵單擊“引用”,選擇“管理 NuGet 程式包”,如下圖。

 

     3.將“nuget.org”選擇為“包源”,選擇“瀏覽”選項卡並搜尋“Microsoft.AspNetCore.Mvc.Formatters.Xml”,在列表中選擇該包,然後選擇“安裝”,如下圖。

 

      4.在Visual Studio 2017中開啟Startup.cs檔案,將 XmlSerializerFormatters 配置新增到 Startup類的ConfigureServices方法中。程式碼如下:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<BookContext>(options =>   options.UseSqlServer(Configuration.GetConnectionString("BookContext"))); 
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddXmlSerializerFormatters(); }

      或者,可以僅新增輸出格式化程式:

services.AddMvc(options =>
{
    options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
});

   通過上面的程式碼我們新增了對 XML 格式的支援,控制器方法會基於請求的 Accept 標頭返回相應的格式。接下來我們來測試一下。

     1) 在Visual Studio 2017中按F5,啟動BookApi應用程式。

     2) 開啟Firefox瀏覽器,並開啟 Rester,在Reseter中,將 HTTP 方法設定為 GET

     3) 選擇“Headers”選項卡,選擇“Accept”選項,並將值設定為 xml (application/xml)。

     4) 使用滑鼠左鍵,單擊“SEND”按鈕。 響應返回200,響應窗格顯示 Content-Type: application/xml 標頭,且 Book 物件已序列化為 XML。如下圖。

 

     5) 選擇“Headers”選項卡,選擇“Accept”選項,並將值設定為 JSON (application/json)。

      6) 使用滑鼠左鍵,單擊“SEND”按鈕。 響應返回200,響應窗格顯示 Content-Type: application/json 標頭,且 Book 物件已序列化為 JSON。如下圖。從圖片中可以看到請求了設定 Accept: application/json 的標頭,且響應也將它指定為其 Content-TypeBOOK 物件以 JSON 格式顯示在響應正文中。


     內容協商過程

      內容協商僅在 Accept 標頭出現在請求中時發生。 請求包含 accept 標頭時,框架會以最佳順序列舉 accept 標頭中的媒體型別,並且嘗試查詢可以生成一種由 accept 標頭指定格式的響應的格式化程式。 如果未找到可以滿足客戶端請求的格式化程式,框架將嘗試找到第一個可以生成響應的格式化程式(除非開發人員配置 MvcOptions 上的選項以返回“406 不可接受”)。 如果請求指定 XML,但是未配置 XML 格式化程式,那麼將使用 JSON 格式化程式。 一般來說,如果沒有配置可以提供所請求格式的格式化程式,那麼使用第一個可以設定物件格式的格式化程式。 如果不提供任何標頭,則將使用第一個可以處理要返回的物件的格式化程式來序列化響應。 在此情況下,沒有任何協商發生 - 伺服器確定將使用的格式。

         如果 Accept 標頭包含 */*,則將忽略該標頭,除非 RespectBrowserAcceptHeaderMvcOptions 上設定為 true。

相關文章