使用ASP.NET Core 3.x 構建 RESTful API P7 P8 內容協商
內容協商 (Content Negotiation)
人們經常將 RESTful API
與 Json
聯繫在一起,是因爲 Json
是 RESTful API
表述,結果的一種方式,但是 RESTful API
表述結果,不僅僅會使用 Json
,也有可能會使用 XML
,以及一些其它自定義的數據格式,那麼到底需要 RESTful API
返回什麼樣的數據格式類型呢?那麼這就叫做 內容協商
,即 API
消費者需要明確的告知, API
它需要什麼樣的返回結果的數據格式,以便返回的結果,能夠得到順利的解析.
- 內容協商:針對一個響應,當有多種表示格式可用的時候,選取最佳的一個表述.
Accept Header
在請求報文中 Accept Hander 是用來告訴Api,消費者需要API來返回什麼樣格式的數據.
- Media Type (媒體類型)
- application/json
- application/xml
- ...
- 如果消費者沒有告訴
API
它需要的數據格式,那麼API
會以API
自己默認的數據格式返回數據. - 如果
消費者
明確告知了API
自己需要的數據格式,但是API
不支持這種數據格式,那麼API
就應該返回406
的HTTP Status Code
,即Not Acceptable
- 輸出格式
- 在 ASP .NET Core 裏面對應的就是 Output Formatters
Content-Type Hander
在請求報文中 Content-Type 是用來告訴 API
,消費者傳遞過來的數據的格式是什麼樣的,以便 API
可以方便的解析消費者的請求參數.
-
Media Type(媒體類型)
- application/json
- application/xml
- ...
-
輸出格式
-
ASP .NET Core 裏面對應的就是Input formatters.
Accept Hander 與 Content-Type Hander 的應用
在默認情況下 ASP .Net Core 使用 JSON 作爲數據輸入和輸出的格式化器.
下面開始寫代碼對上理論進行驗證
如當消費者要求的返回格式,API
不支持,那麼 API
應該返回相應的 HTTP 狀態碼.
爲此在 ASP .Net Core 中,我們需要在 Startup.cs 文件的 ConfigureServices 方法中編寫以下代碼:
services.AddControllers(setup =>
{
//例子:當消費者要求返回的數據格式是json時,如果服務器端默認的就是xml格式,而且僅僅只支持xml格式,
//那麼默認的就會將xml格式返回回去,並且不會返回406狀態碼,所以ReturnHttpNotAcceptable的默認值就是false
//setup.ReturnHttpNotAcceptable = false;
//當爲true時,表示當消費者要求的返回的數據類型,與數據庫支持的返回的數據類型不一致時,
//就會返回 HTTP 狀態碼 406 ,也就是NotAcceptable
setup.ReturnHttpNotAcceptable = true;
});
當我們將 ReturnHttpNotAcceptable 的值設置爲true時,表示當消費者要求返回的數據格式,不被服務器所支持,那麼服務器就會返回406,如圖:
那麼我們讓我們的 API
既支持json格式的返回,也支持xml格式的返回呢?
我們可以將代碼這麼寫,如下:
services.AddControllers(setup =>
{
//例子:當消費者要求返回的數據格式是json時,如果服務器端默認的就是xml格式,而且僅僅只支持xml格式,
//那麼默認的就會將xml格式返回回去,並且不會返回406狀態碼,所以ReturnHttpNotAcceptable的默認值就是false
//setup.ReturnHttpNotAcceptable = false;
//當爲true時,表示當消費者要求的返回的數據類型,與數據庫支持的返回的數據類型不一致時,
//就會返回 HTTP 狀態碼 406 ,也就是NotAcceptable
setup.ReturnHttpNotAcceptable = true;
//OutputFormatters是一個集合,這個集合裏面可以放置多個格式化器,用來支持多種消費者要求的返回格式,
//這OutputFormatters中的第一個元素設置,就是這個集合默認的返回格式的格式化器,默認情況下OutputFormatters
//中只有一個json格式化器.
//下面我們添加對xml格式化器的支持
//setup.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
//如果我們想添加xml格式化器,並使其成爲默認的數據格式化器,那麼我們使用如下寫法即可:
//那麼當消費者沒有要求返回格式時,API會默認返回xml格式的數據.
setup.OutputFormatters.Insert(0, new XmlDataContractSerializerOutputFormatter());
});
請求返回的數據如下:
請求返回的數據格式如下:
此時我們要求 API
返回Json格式的數據也是可以的,因爲 API
也支持了返回Json的設置,如下:
此處我們需要注意:千萬不能在Action中使用return new JsonResult(對象);
的形式來返回數據,否則就不能根據消費者要求的數據格式來返回數據了.
那麼我們如何支持輸入參數的數據格式的支持呢?
使用方式和 OutputFormatters
是一樣的存在一個叫InputFormatters
,它的使用方式和OutputFormatters
, 是一樣的,代碼如下:
//添加對請求參數格式是xml的支持
setup.InputFormatters.Insert(0,new XmlDataContractSerializerInputFormatter(setup));
但是上述寫法都只是 ASP .Net Core 3.x 之前的寫法,在3.x 之後的寫法是這樣的,代碼如下:
services.AddControllers(setup =>
{
setup.ReturnHttpNotAcceptable = true;
}).AddXmlDataContractSerializerFormatters();
我們可以接在 AddControllers() 方法之後,接着寫 .AddXmlDataContractSerializerFormatters()
方法即可,它既表明支持消費者傳入的參數是xml格式,也支持消費者要求的返回數據格式是xml.