设置 ASP.NET Core Web API 中响应数据的格式Format response data in ASP.NET Core Web API

本文内容

作者:Rick AndersonSteve Smith

ASP.NET Core MVC 支持设置响应数据的格式。可以使用特定格式或响应客户端请求的格式,来设置响应数据的格式。

查看或下载示例代码如何下载

特定于格式的操作结果Format-specific Action Results

一些操作结果类型特定于特殊格式,例如 JsonResultContentResult操作可以返回使用特定格式设置格式的结果,而不考虑客户端首选项。例如,返回 JsonResult,将返回 JSON 格式的数据。返回 ContentResult 或字符串,将返回纯文本格式的字符串数据。

无需操作返回任意特定类型。ASP.NET Core 支持任何对象返回值。返回非 IActionResult 类型对象的操作结果将使用相应的 IOutputFormatter 实现来进行序列化。有关详细信息,请参阅 ASP.NET Core Web API 中控制器操作的返回类型

内置的帮助程序方法 Ok 返回 JSON 格式的数据:[!code-csharp]

示例下载返回作者列表。在 F12 浏览器开发人员工具或 Postman 中使用上述代码:

  • 将显示包含content-type: application/json; charset=utf-8 的响应标头。
  • 将显示请求标头。例如 Accept 标头。上述代码将忽略 Accept 标头。

若要返回纯文本格式数据,请使用 ContentContent 帮助程序:

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

在上述代码中,返回的 Content-Typetext/plain返回字符串,将提供 Content-Type 类型的 text/plain

  1. // GET api/authors/version
  2. [HttpGet("version")]
  3. public string Version()
  4. {
  5. return "Version 1.0.0";
  6. }

对于包含多个返回类型的操作,将返回 IActionResult例如,基于执行的操作的结果返回不同的 HTTP 状态代码。

内容协商Content negotiation

当客户端指定 Accept 标头时,会发生内容协商。ASP.NET Core 使用的默认格式是 JSON内容协商有以下特点:

  • ObjectResult 实现。
  • 内置于从帮助程序方法返回的特定于状态代码的操作结果中。操作结果帮助程序方法基于 ObjectResult

返回模型类型后,返回类型为 ObjectResult

以下操作方法使用 OkNotFound 帮助程序方法:

  1. // GET: api/authors/search?namelike=th
  2. [HttpGet("Search")]
  3. public IActionResult Search(string namelike)
  4. {
  5. var result = _authors.GetByNameSubstring(namelike);
  6. if (!result.Any())
  7. {
  8. return NotFound(namelike);
  9. }
  10. return Ok(result);
  11. }

默认情况下,ASP.NET Core 支持 application/jsontext/jsontext/plain 媒体类型。FiddlerPostman 等工具可以设置 Accept 请求标头,来指定返回格式。Accept 标头包含服务器支持的类型时,将返回该类型。下一节将介绍如何添加其他格式化程序。

控制器操作可以返回 POCO(普通旧 CLR 对象)。返回 POCO 时,运行时自动创建包装该对象的 ObjectResult客户端将获得已格式化和序列化的对象。若将返回的对象为 null,将返回 204 No Content 响应。

返回对象类型:

  1. // GET api/authors/RickAndMSFT
  2. [HttpGet("{alias}")]
  3. public Author Get(string alias)
  4. {
  5. return _authors.GetByAlias(alias);
  6. }

在前面的代码中,请求有效作者别名将返回具有作者数据的 200 OK 响应。请求无效别名将返回 204 No Content 响应。

Accept 标头The Accept header

内容协商在 标头出现在请求中时发生Accept请求包含 Accept 标头时,ASP.NET Core 将执行以下操作:

  • 按首选顺序枚举 Accept 标头中的媒体类型。
  • 尝试找到可以生成某种指定格式的响应的格式化程序。

若未找到可以满足客户端请求的格式化程序,ASP.NET Core 将指定以下操作:

  • 已设置 406 Not Acceptable 时,将返回 MvcOptions,或者
  • 尝试找到第一个可以生成响应的格式化程序。

如果没有配置实现所请求格式的格式化程序,那么使用第一个可以设置对象格式的格式化程序。若请求中没有 Accept 标头:

  • 将使用第一个可以处理对象的格式化程序来将响应序列化。
  • 不执行任何协商。服务器将决定要返回的格式。

如果 Accept 标头包含 /,则将忽略该标头,除非 RespectBrowserAcceptHeaderMvcOptions 上设置为 true。

浏览器和内容协商Browsers and content negotiation

与典型的 API 客户端不同的是,Web 浏览器提供 Accept 标头。Web 浏览器指定多种格式,包括通配符。默认情况下,当框架检测到请求来自浏览器时,将执行以下操作:

  • 忽略 Accept 标头。
  • 若未另行配置,将使用 JSON 返回内容。

这样,在使用 API 时,浏览器中的体验将更加一致。

若要将应用配置为采用浏览器 Accept 标头,请将 RespectBrowserAcceptHeader 设置为 true

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllers(options =>
  4. {
  5. options.RespectBrowserAcceptHeader = true; // false by default
  6. });
  7. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc(options =>
  4. {
  5. options.RespectBrowserAcceptHeader = true; // false by default
  6. });
  7. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  8. }

配置格式化程序Configure formatters

需要支持其他格式的应用可以添加相应的 NuGet 包,并配置支持。输入和输出的格式化程序不同。模型绑定使用输入格式化程序。格式响应使用输出格式化程序。有关创建自定义格式化程序的信息,请参阅自定义格式化程序

添加 XML 格式支持Add XML format support

调用 XmlSerializer 来配置使用 AddXmlSerializerFormatters 实现的 XML 格式化程序:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllers()
  4. .AddXmlSerializerFormatters();
  5. }

前面的代码将使用 XmlSerializer 将结果序列化。

使用前面的代码时,控制器方法会基于请求的 Accept 标头返回相应的格式。

配置基于 System.Text.Json 的格式化程序Configure System.Text.Json-based formatters

可以使用 System.Text.Json 配置基于 Microsoft.AspNetCore.Mvc.JsonOptions.SerializerOptions 的格式化程序的功能。

  1. services.AddControllers().AddJsonOptions(options =>
  2. {
  3. // Use the default property (Pascal) casing.
  4. options.SerializerOptions.PropertyNamingPolicy = null;
  5. // Configure a custom converter.
  6. options.SerializerOptions.Converters.Add(new MyCustomJsonConverter());
  7. });

可以使用 JsonResult 配置基于每个操作的输出序列化选项。例如:

  1. public IActionResult Get()
  2. {
  3. return Json(model, new JsonSerializerOptions
  4. {
  5. options.WriteIndented = true,
  6. });
  7. }

添加基于 Newtonsoft.Json 的 JSON 格式支持Add Newtonsoft.Json-based JSON format support

ASP.NET Core 3.0 之前的版本中,默认设置使用通过 Newtonsoft.Json 包实现的 JSON 格式化程序。在 ASP.NET Core 3.0 或更高版本中,默认 JSON 格式化程序基于 System.Text.Json通过安装 Newtonsoft.JsonMicrosoft.AspNetCore.Mvc.NewtonsoftJson NuGet 包并在 中配置可以支持基于 Startup.ConfigureServices 的格式化程序和功能。

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllers()
  4. .AddNewtonsoftJson();
  5. }

某些功能可能不适用于基于 System.Text.Json 的格式化程序,而需要引用基于 Newtonsoft.Json 的格式化程序。若应用符合以下情况,请继续使用基于 Newtonsoft.Json 的格式化程序:

  • 使用 Newtonsoft.Json 属性。例如,[JsonProperty][JsonIgnore]
  • 自定义序列化设置。
  • 依赖 Newtonsoft.Json 提供的功能。
  • 配置 Microsoft.AspNetCore.Mvc.JsonResult.SerializerSettings。ASP.NET Core 3.0 之前的版本中,JsonResult.SerializerSettings 接受特定于 JsonSerializerSettingsNewtonsoft.Json 的实例。
  • 生成 OpenAPI 文档。

可以使用 Newtonsoft.Json 配置基于 Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings 的格式化程序的功能:

  1. services.AddControllers().AddNewtonsoftJson(options =>
  2. {
  3. // Use the default property (Pascal) casing
  4. options.SerializerSettings.ContractResolver = new DefaultContractResolver();
  5. // Configure a custom converter
  6. options.SerializerOptions.Converters.Add(new MyCustomJsonConverter());
  7. });

可以使用 JsonResult 配置基于每个操作的输出序列化选项。例如:

  1. public IActionResult Get()
  2. {
  3. return Json(model, new JsonSerializerSettings
  4. {
  5. options.Formatting = Formatting.Indented,
  6. });
  7. }

添加 XML 格式支持Add XML format support

XML 格式需要 Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet 包。

调用 XmlSerializer 来配置使用 AddXmlSerializerFormatters 实现的 XML 格式化程序:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc()
  4. .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
  5. .AddXmlSerializerFormatters();
  6. }

前面的代码将使用 XmlSerializer 将结果序列化。

使用前面的代码时,控制器方法应基于请求的 Accept 标头返回相应的格式。

指定格式Specify a format

应用 [Produces] 筛选器,以限制响应格式。如同大多筛选器[Produces] 可以在操作层面、控制器层面或全局范围内应用:

  1. [ApiController]
  2. [Route("[controller]")]
  3. [Produces("application/json")]
  4. public class WeatherForecastController : ControllerBase
  5. {

上述 [Produces] 筛选器将执行以下操作:

  • 强制控制器内的所有操作返回 JSON 格式的响应。
  • 若已配置其他格式化程序,并且客户端指定了其他格式,将返回 JSON。

有关详细信息,请参阅筛选器

特例格式化程序Special case formatters

一些特例是使用内置格式化程序实现的。默认情况下,string 返回类型的格式将设为 text/plain(如果通过 标头请求则为 text/html) Accept可以通过删除 StringOutputFormatter 删除此行为。ConfigureServices 方法中删除格式化程序。有模型对象返回类型的操作将在返回 204 No Content 时返回 null可以通过删除 HttpNoContentOutputFormatter 删除此行为。以下代码删除 StringOutputFormatterHttpNoContentOutputFormatter

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllers(options =>
  4. {
  5. // requires using Microsoft.AspNetCore.Mvc.Formatters;
  6. options.OutputFormatters.RemoveType<StringOutputFormatter>();
  7. options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
  8. });
  9. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc(options =>
  4. {
  5. // requires using Microsoft.AspNetCore.Mvc.Formatters;
  6. options.OutputFormatters.RemoveType<StringOutputFormatter>();
  7. options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
  8. });
  9. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  10. }

如果没有 StringOutputFormatter,内置 JSON 格式化程序将设置 string 返回类型的格式。如果删除了内置 JSON 格式化程序并提供了 XML 格式化程序,则 XML 格式化程序将设置 string 返回类型的格式。否则,string 返回类型返回 406 Not Acceptable

没有 HttpNoContentOutputFormatter,null 对象将使用配置的格式化程序来进行格式设置。例如:

  • JSON 格式化程序返回正文为 null 的响应。
  • 设置属性 xsi:nil="true" 时,XML 格式化程序返回空 XML 元素。

响应格式 URL 映射Response format URL mappings

客户端可以在 URL 中请求特定格式,例如:

  • 在查询字符串中,或在路径中。
  • 使用格式特定的文件扩展名,如 .xml 或 .json。

请求路径的映射必须在 API 使用的路由中指定。例如:

  1. [Route("api/[controller]")]
  2. [ApiController]
  3. [FormatFilter]
  4. public class ProductsController : ControllerBase
  5. {
  6. [HttpGet("{id}.{format?}")]
  7. public Product Get(int id)
  8. {

上述路由将允许指定所请求格式为可选文件扩展名。[FormatFilter] 属性检查 RouteData 中格式值是否存在,并在响应创建时将响应格式映射到相应格式化程序。

路由格式化程序
/api/products/5默认输出格式化程序
/api/products/5.jsonJSON 格式化程序(如配置)
/api/products/5.xmlXML 格式化程序(如配置)