在 ASP.NET Core Web API 中格式化回應資料Format response data in ASP.NET Core Web API

作者:Steve SmithBy Steve Smith

ASP.NET Core MVC 具有使用固定格式或回應用戶端規格的內建回應資料格式化支援。ASP.NET Core MVC has built-in support for formatting response data, using fixed formats or in response to client specifications.

檢視或下載範例程式碼 (英文) (如何下載)View or download sample code (how to download)

格式特定動作結果Format-Specific Action Results

某些動作結果類型是特定格式所特有的,例如 JsonResultContentResultSome action result types are specific to a particular format, such as JsonResult and ContentResult. 動作可以傳回一律以特定方式格式化的特定結果。Actions can return specific results that are always formatted in a particular manner. 例如,不論用戶端喜好設定為何,傳回 JsonResult 都會傳回 JSON 格式化資料。For example, returning a JsonResult will return JSON-formatted data, regardless of client preferences. 同樣地,傳回 ContentResult 將會傳回純文字格式化字串資料 (就像只傳回字串一樣)。Likewise, returning a ContentResult will return plain-text-formatted string data (as will simply returning a string).

注意

動作不要求任何特定的型別,MVC 支援任何物件的傳回值。An action isn't required to return any particular type; MVC supports any object return value. 如果動作回傳 IActionResult 的實作並且「控制器」 繼承自 Controller,開發人員會有許多對應至多種選項的輔助方法。If an action returns an IActionResult implementation and the controller inherits from Controller, developers have many helper methods corresponding to many of the choices. 回傳物件的動作結果不是 IActionResult 型別會使用適當的序列化 IOutputFormatter 實作。Results from actions that return objects that are not IActionResult types will be serialized using the appropriate IOutputFormatter implementation.

若要從繼承自 Controller 基底類別的控制器傳回特定格式的資料,請使用內建協助程式方法 Json 傳回 JSON 和 Content (針對純文字)。To return data in a specific format from a controller that inherits from the Controller base class, use the built-in helper method Json to return JSON and Content for plain text. 動作方法應該會傳回特定結果類型 (例如,JsonResult) 或 IActionResultYour action method should return either the specific result type (for instance, JsonResult) or IActionResult.

傳回 JSON 格式化資料:Returning JSON-formatted data:

// GET: api/authors
[HttpGet]
public JsonResult Get()
{
    return Json(_authorRepository.List());
}

此動作的範例回應:Sample response from this action:

Microsoft Edge 中 [開發人員工具] 的 [網路] 索引標籤,顯示回應的內容類型為 application/json

請注意,在網路要求清單及 [回應標頭] 區段中,回應的內容類型都是 application/jsonNote that the content type of the response is application/json, shown both in the list of network requests and in the Response Headers section. 另請注意,在 [要求標頭] 區段的 Accept 標頭中瀏覽器 (在此情況下為 Microsoft Edge) 所呈現的選項清單。Also note the list of options presented by the browser (in this case, Microsoft Edge) in the Accept header in the Request Headers section. 目前技術將會忽略此標頭。下面會討論其遵守方式。The current technique is ignoring this header; obeying it is discussed below.

若要傳回純文字格式化資料,請使用 ContentResultContent 協助程式:To return plain text formatted data, use ContentResult and the Content helper:

// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
    return Content("An API listing authors of docs.asp.net.");
}

此動作的回應:A response from this action:

Microsoft Edge 中 [開發人員工具] 的 [網路] 索引標籤,顯示回應的內容類型為 text/plain

請注意,在此情況下,所傳回的 Content-Typetext/plainNote in this case the Content-Type returned is text/plain. 只要使用字串回應類型,也可以達到這個相同的行為:You can also achieve this same behavior using just a string response type:

// GET api/authors/version
[HttpGet("version")]
public string Version()
{
    return "Version 1.0.0";
}

提示

針對具有多個傳回類型或選項 (例如,根據所執行作業結果的不同 HTTP 狀態碼) 的非一般動作,偏好使用 IActionResult 作為傳回類型。For non-trivial actions with multiple return types or options (for example, different HTTP status codes based on the result of operations performed), prefer IActionResult as the return type.

內容交涉Content Negotiation

用戶端指定 Accept 標頭時,會進行內容交涉 (簡稱 conneg)。Content negotiation (conneg for short) occurs when the client specifies an Accept header. ASP.NET Core MVC 預設使用 JSON 格式。The default format used by ASP.NET Core MVC is JSON. 內容交涉是由 ObjectResult 所實作。Content negotiation is implemented by ObjectResult. 它也會內建到從協助程式方法 (全部都是根據 ObjectResult) 所傳回的狀態碼特定動作結果。It's also built into the status code specific action results returned from the helper methods (which are all based on ObjectResult). 您也可以傳回模型類型 (已定義為資料傳輸類型的類別),而且架構會自動將它包裝在 ObjectResult 中。You can also return a model type (a class you've defined as your data transfer type) and the framework will automatically wrap it in an ObjectResult for you.

下列動作方法使用 OkNotFound 協助程式方法:The following action method uses the Ok and NotFound helper methods:

// GET: api/authors/search?namelike=th
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
    var result = _authorRepository.GetByNameSubstring(namelike);
    if (!result.Any())
    {
        return NotFound(namelike);
    }
    return Ok(result);
}

除非要求另一種格式,而且伺服器可以傳回所要求的格式,否則會傳回 JSON 格式的回應。A JSON-formatted response will be returned unless another format was requested and the server can return the requested format. 您可以使用 Fiddler 這類工具建立包含 Accept 標頭的要求,以及指定另一種格式。You can use a tool like Fiddler to create a request that includes an Accept header and specify another format. 在此情況下,如果伺服器的「格式器」 可以使用所要求的格式產生回應,則會以用戶端慣用的格式傳回結果。In that case, if the server has a formatter that can produce a response in the requested format, the result will be returned in the client-preferred format.

Fiddler 主控台,顯示 Accept 標頭值為 application/xml 的手動建立 GET 要求

在上面的螢幕擷取畫面中,已使用 Fiddler Composer 來產生要求,並指定 Accept: application/xmlIn the above screenshot, the Fiddler Composer has been used to generate a request, specifying Accept: application/xml. ASP.NET Core MVC 預設僅支援 JSON;因此,即使指定另一種格式,所傳回的結果仍然會是 JSON 格式。By default, ASP.NET Core MVC only supports JSON, so even when another format is specified, the result returned is still JSON-formatted. 您將在下節中看到如何新增其他格式器。You'll see how to add additional formatters in the next section.

控制器動作可以傳回 POCO (簡單的 CLR 物件),在此情況下,ASP.NET Core MVC 會自動建立可包裝物件的 ObjectResultController actions can return POCOs (Plain Old CLR Objects), in which case ASP.NET Core MVC automatically creates an ObjectResult for you that wraps the object. 用戶端會取得格式化的序列化物件 (JSON 格式是預設值;您可以設定 XML 或其他格式)。The client will get the formatted serialized object (JSON format is the default; you can configure XML or other formats). 如果所傳回的物件是 null,則架構將傳回 204 No Content 回應。If the object being returned is null, then the framework will return a 204 No Content response.

傳回物件類型:Returning an object type:

// GET api/authors/ardalis
[HttpGet("{alias}")]
public Author Get(string alias)
{
    return _authorRepository.GetByAlias(alias);
}

在此範例中,有效作者別名的要求將會收到包含作者資料的 200 OK 回應。In the sample, a request for a valid author alias will receive a 200 OK response with the author's data. 無效別名的要求將會收到「204 沒有內容」回應。A request for an invalid alias will receive a 204 No Content response. 下面顯示以 XML 和 JSON 格式顯示回應的螢幕擷取畫面。Screenshots showing the response in XML and JSON formats are shown below.

內容交涉程序Content Negotiation Process

只有在 Accept 標頭出現在要求中時,才會進行「內容交涉」 。Content negotiation only takes place if an Accept header appears in the request. 要求包含 Accept 標頭時,架構會依喜好設定順序來列舉 Accept 標頭中的媒體類型,並嘗試尋找可產生回應的格式器,而回應的格式為 Accept 標頭所指定的其中一種格式。When a request contains an accept header, the framework will enumerate the media types in the accept header in preference order and will try to find a formatter that can produce a response in one of the formats specified by the accept header. 如果找不到可滿足用戶端要求的格式器,架構會嘗試尋找第一個可產生回應的格式器 (除非開發人員已在 MvcOptions 上設定選項,改為傳回「406 無法接受」)。In case no formatter is found that can satisfy the client's request, the framework will try to find the first formatter that can produce a response (unless the developer has configured the option on MvcOptions to return 406 Not Acceptable instead). 如果要求指定 XML,但尚未設定 XML 格式器,則會使用 JSON 格式器。If the request specifies XML, but the XML formatter has not been configured, then the JSON formatter will be used. 更常見地是,如果未設定格式器來提供所要求的格式,則會使用可格式化物件的第一個格式器。More generally, if no formatter is configured that can provide the requested format, then the first formatter that can format the object is used. 如果未指定標頭,則會使用可處理要傳回之物件的第一個格式器來序列化回應。If no header is given, the first formatter that can handle the object to be returned will be used to serialize the response. 在此情況下,無法進行任何交涉,伺服器將會判斷所使用的格式。In this case, there isn't any negotiation taking place - the server is determining what format it will use.

注意

如果 Accept 標頭包含 */*,則除非 MvcOptions 上的 RespectBrowserAcceptHeader 設定為 true,否則會忽略標頭。If the Accept header contains */*, the Header will be ignored unless RespectBrowserAcceptHeader is set to true on MvcOptions.

瀏覽器和內容交涉Browsers and Content Negotiation

與一般 API 用戶端不同,網頁瀏覽器會提供 Accept 標頭,內含廣泛的格式陣列 (包括萬用字元)。Unlike typical API clients, web browsers tend to supply Accept headers that include a wide array of formats, including wildcards. 根據預設,架構偵測到要求來自瀏覽器時,將會忽略 Accept 標頭,並改為傳回應用程式中已設定預設格式 (除非另外設定,否則為 JSON ) 的內容。By default, when the framework detects that the request is coming from a browser, it will ignore the Accept header and instead return the content in the application's configured default format (JSON unless otherwise configured). 使用不同的瀏覽器來採用 API 時,這提供更一致的經驗。This provides a more consistent experience when using different browsers to consume APIs.

如果您想要應用程式採用瀏覽器 Accept 標頭,則可以將這設定為 MVC 組態的一部分,方法是在 Startup.csConfigureServices 方法中將 RespectBrowserAcceptHeader 設定為 trueIf you would prefer your application honor browser accept headers, you can configure this as part of MVC's configuration by setting RespectBrowserAcceptHeader to true in the ConfigureServices method in Startup.cs.

services.AddMvc(options =>
{
    options.RespectBrowserAcceptHeader = true; // false by default
});

設定格式器Configuring Formatters

如果您的應用程式需要支援 JSON 預設值以外的其他格式,則可以新增 NuGet 套件,並設定 MVC 來支援它們。If your application needs to support additional formats beyond the default of JSON, you can add NuGet packages and configure MVC to support them. 輸入和輸出有個別的格式器。There are separate formatters for input and output. 模型繫結會使用輸入格式器;輸出格式器是用來格式化回應。Input formatters are used by Model Binding; output formatters are used to format responses. 您也可以設定自訂格式器You can also configure Custom Formatters.

設定 System.Text.Json-based 格式器Configure System.Text.Json-based formatters

System.Text.Json 型格式器可以使用 Microsoft.AspNetCore.Mvc.MvcOptions.SerializerOptions 來設定。Features for the System.Text.Json-based formatters can be configured using Microsoft.AspNetCore.Mvc.MvcOptions.SerializerOptions.

services.AddMvc(options =>
{
    options.SerializerOptions.WriterSettings.Indented = true;
});

新增 Newtonsoft.Json 型 JSON 格式支援Add Newtonsoft.Json-based JSON format support

在 ASP.NET Core 3.0 之前,MVC 預設為使用以 Newtonsoft.Json 套件實作的 JSON 格式器。Prior to ASP.NET Core 3.0, MVC defaulted to using JSON formatters implemented using the Newtonsoft.Json package. 在 ASP.NET Core 3.0 或更新版本中,預設 JSON 格式器是以 System.Text.Json 為基礎。In ASP.NET Core 3.0 or later, the default JSON formatters are based on System.Text.Json. Newtonsoft.Json 型格式器與功能的支援可透過安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet 套件並在 Startup.ConfigureServices 中設定它來取得。Support for Newtonsoft.Json-based formatters and features is available by installing the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package and configuring it in Startup.ConfigureServices.

services.AddMvc()
    .AddNewtonsoftJson();

某些功能可能無法搭配System.Text.Json 型格式器使用,而且需要對 ASP.NET Core 3.0 版本之 Newtonsoft.Json 型格式器的參考。Some features may not work well with System.Text.Json-based formatters and require a reference to the Newtonsoft.Json-based formatters for the ASP.NET Core 3.0 release. 若您的 ASP.NET Core 3.0 或更新版本應用程式符合下列條件,請繼續使用 Newtonsoft.Json 型格式器:Continue using the Newtonsoft.Json-based formatters if your ASP.NET Core 3.0 or later app:

  • 使用 Newtonsoft.Json 屬性 (例如 [JsonProperty][JsonIgnore]) 自訂序列化設定,或仰賴 Newtonsoft.Json 所提供的功能。Uses Newtonsoft.Json attributes (for example, [JsonProperty] or [JsonIgnore]), customizes the serialization settings, or relies on features that Newtonsoft.Json provides.
  • 設定 Microsoft.AspNetCore.Mvc.JsonResult.SerializerSettingsConfigures Microsoft.AspNetCore.Mvc.JsonResult.SerializerSettings. 在 ASP.NET Core 3.0 版之前,JsonResult.SerializerSettings 接受 Newtonsoft.Json 專屬的 JsonSerializerSettings 執行個體。Prior to ASP.NET Core 3.0, JsonResult.SerializerSettings accepts an instance of JsonSerializerSettings that is specific to Newtonsoft.Json.
  • 產生 OpenAPI 文件。Generates OpenAPI documentation.

新增 XML 格式支援Add XML format support

若要在 ASP.NET Core 2.2 或更早版本中新增 XML 格式支援,請安裝 Microsoft.AspNetCore.Mvc.Formatters.Xml (英文) NuGet 套件。To add XML formatting support in ASP.NET Core 2.2 or earlier, install the Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet package.

使用 System.Xml.Serialization.XmlSerializer 實作的 XML 格式器可以透過呼叫 Startup.ConfigureServices 中的 AddXmlSerializerFormatters 來設定:XML formatters implemented using System.Xml.Serialization.XmlSerializer can be configured by calling AddXmlSerializerFormatters in Startup.ConfigureServices:

services.AddMvc()
    .AddXmlSerializerFormatters();

或者,使用 System.Runtime.Serialization.DataContractSerializer 實作的 XML 格式器可以透過呼叫 Startup.ConfigureServices 中的 AddXmlDataContractSerializerFormatters 來設定:Alternatively, XML formatters implemented using System.Runtime.Serialization.DataContractSerializer can be configured by calling AddXmlDataContractSerializerFormatters in Startup.ConfigureServices:

services.AddMvc()
    .AddXmlDataContractSerializerFormatters();

新增 XML 格式支援之後,控制器方法應該會根據要求的 Accept 標頭來傳回適當的格式,如這個 Fiddler 範例所示範:Once you've added support for XML formatting, your controller methods should return the appropriate format based on the request's Accept header, as this Fiddler example demonstrates:

Fiddler 主控台:要求的 [原始] 索引標籤會顯示 Accept 標頭值為 application/xml。

您可以在 [偵測器] 索引標籤中看到已設定 Accept: application/xml 標頭來提出原始 GET 要求。You can see in the Inspectors tab that the Raw GET request was made with an Accept: application/xml header set. 回應窗格會顯示 Content-Type: application/xml 標頭,並已將 Author 物件序列化為 XML。The response pane shows the Content-Type: application/xml header, and the Author object has been serialized to XML.

使用 [編輯器] 索引標籤,修改在 Accept 標頭中指定 application/json 的要求。Use the Composer tab to modify the request to specify application/json in the Accept header. 執行要求,並將回應格式化為 JSON:Execute the request, and the response will be formatted as JSON:

Fiddler 主控台:要求的 [原始] 索引標籤會顯示 Accept 標頭值為 application/json。

在此螢幕擷取畫面中,您可以看到要求設定 Accept: application/json 標頭,而回應指定與其 Content-Type 相同的值。In this screenshot, you can see the request sets a header of Accept: application/json and the response specifies the same as its Content-Type. Author 物件會以 JSON 格式顯示在回應本文中。The Author object is shown in the body of the response, in JSON format.

強制執行特定格式Forcing a Particular Format

如果您想要限制特定動作的回應格式,則可以套用 [Produces] 篩選。If you would like to restrict the response formats for a specific action you can, you can apply the [Produces] filter. [Produces] 篩選可指定特定動作 (或控制器) 的回應格式。The [Produces] filter specifies the response formats for a specific action (or controller). 與大部分篩選類似,這可以套用至動作、控制器或全域範圍。Like most Filters, this can be applied at the action, controller, or global scope.

[Produces("application/json")]
public class AuthorsController

[Produces] 篩選將強制執行 AuthorsController 內的所有動作,以傳回 JSON 格式化回應,即使已設定應用程式和用戶端的其他格式器也是一樣,但前提是 Accept 標頭要求不同且可用的格式。The [Produces] filter will force all actions within the AuthorsController to return JSON-formatted responses, even if other formatters were configured for the application and the client provided an Accept header requesting a different, available format. 若要深入了解,請參閱篩選 (包括如何全域套用篩選)。See Filters to learn more, including how to apply filters globally.

特殊案例格式器Special Case Formatters

有些特殊案例是使用內建格式器所實作。Some special cases are implemented using built-in formatters. 根據預設,string 傳回類型將會格式化為 text/plain (如果透過 Accept 標頭要求,則為 text/html)。By default, string return types will be formatted as text/plain (text/html if requested via Accept header). 移除 TextOutputFormatter,即可移除此行為。This behavior can be removed by removing the TextOutputFormatter. 您可以在 Startup.csConfigure 方法中移除格式器 (如下所示)。You remove formatters in the Configure method in Startup.cs (shown below). 傳回 null 時,具有模型物件傳回類型的動作會傳回「204 沒有內容」回應。Actions that have a model object return type will return a 204 No Content response when returning null. 移除 HttpNoContentOutputFormatter,即可移除此行為。This behavior can be removed by removing the HttpNoContentOutputFormatter. 下列程式碼會移除 TextOutputFormatterHttpNoContentOutputFormatterThe following code removes the TextOutputFormatter and HttpNoContentOutputFormatter.

services.AddMvc(options =>
{
    options.OutputFormatters.RemoveType<TextOutputFormatter>();
    options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});

例如,如果沒有 TextOutputFormatter,則 string 傳回類型會傳回「406 無法接受」。Without the TextOutputFormatter, string return types return 406 Not Acceptable, for example. 請注意,如果存在 XML 格式器,則移除 TextOutputFormatter 時,會格式化 string 傳回類型。Note that if an XML formatter exists, it will format string return types if the TextOutputFormatter is removed.

如果沒有 HttpNoContentOutputFormatter,則會使用已設定的格式器來格式化 Null 物件。Without the HttpNoContentOutputFormatter, null objects are formatted using the configured formatter. 例如,JSON 格式器只會傳回本文為 null 的回應,而 XML 格式器將會傳回已設定屬性 xsi:nil="true" 的空白 XML 項目。For example, the JSON formatter will simply return a response with a body of null, while the XML formatter will return an empty XML element with the attribute xsi:nil="true" set.

回應格式 URL 對應Response Format URL Mappings

用戶端可以要求特定格式作為 URL 的一部分 (例如在查詢字串中或作為路徑的一部分),或是使用格式特定副檔名 (例如 .xml 或 .json)。Clients can request a particular format as part of the URL, such as in the query string or part of the path, or by using a format-specific file extension such as .xml or .json. 應該在 API 所使用的路由中指定要求路徑的對應。The mapping from request path should be specified in the route the API is using. 例如:For example:

[FormatFilter]
public class ProductsController
{
    [Route("[controller]/[action]/{id}.{format?}")]
    public Product GetById(int id)

此路由可將所要求的格式指定為選擇性副檔名。This route would allow the requested format to be specified as an optional file extension. [FormatFilter] 屬性會檢查 RouteData 中是否有格式值,並在建立回應時將回應格式對應至適當的格式器。The [FormatFilter] attribute checks for the existence of the format value in the RouteData and will map the response format to the appropriate formatter when the response is created.

路由Route 格式器Formatter
/products/GetById/5 預設輸出格式器The default output formatter
/products/GetById/5.json JSON 格式器 (如果已設定)The JSON formatter (if configured)
/products/GetById/5.xml XML 格式器 (如果已設定)The XML formatter (if configured)