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

作者:Rick AndersonSteve Smith

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

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

特定于格式的操作结果

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

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

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

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

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

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

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

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

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

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

内容协商

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

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

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

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

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

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

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

返回对象类型:

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

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

Accept 标头

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

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

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

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

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

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

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

浏览器和内容协商

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

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

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

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.RespectBrowserAcceptHeader = true; // false by default
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.RespectBrowserAcceptHeader = true; // false by default
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

配置格式化程序

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

添加 XML 格式支持

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddXmlSerializerFormatters();
}

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

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

配置基于 System.Text.Json 的格式化程序

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

services.AddControllers().AddJsonOptions(options =>
{
    // Use the default property (Pascal) casing.
    options.SerializerOptions.PropertyNamingPolicy = null;

    // Configure a custom converter.
    options.SerializerOptions.Converters.Add(new MyCustomJsonConverter());
});

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

public IActionResult Get()
{
    return Json(model, new JsonSerializerOptions
    {
        options.WriteIndented = true,
    });
}

添加基于 Newtonsoft.Json 的 JSON 格式支持

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddNewtonsoftJson();
}

某些功能可能不适用于基于 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 接受特定于 Newtonsoft.JsonJsonSerializerSettings 的实例。
  • 生成 OpenAPI 文档。

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

services.AddControllers().AddNewtonsoftJson(options =>
{
    // Use the default property (Pascal) casing
    options.SerializerSettings.ContractResolver = new DefaultContractResolver();

    // Configure a custom converter
    options.SerializerOptions.Converters.Add(new MyCustomJsonConverter());
});

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

public IActionResult Get()
{
    return Json(model, new JsonSerializerSettings
    {
        options.Formatting = Formatting.Indented,
    });
}

添加 XML 格式支持

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

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddXmlSerializerFormatters();
}

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

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

指定格式

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

[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{

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

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

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

特例格式化程序

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        // requires using Microsoft.AspNetCore.Mvc.Formatters;
        options.OutputFormatters.RemoveType<StringOutputFormatter>();
        options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        // requires using Microsoft.AspNetCore.Mvc.Formatters;
        options.OutputFormatters.RemoveType<StringOutputFormatter>();
        options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

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

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

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

响应格式 URL 映射

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

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

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

[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
    [HttpGet("{id}.{format?}")]
    public Product Get(int id)
    {

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

路由 格式化程序
/api/products/5 默认输出格式化程序
/api/products/5.json JSON 格式化程序(如配置)
/api/products/5.xml XML 格式化程序(如配置)

上一篇:ASP.NET Core Web API 中的 JSON 修补程序

下一篇:ASP.NET Core Web API 中的自定义格式化程序

关注微信小程序
程序员编程王-随时随地学编程

扫描二维码
程序员编程王

扫一扫关注最新编程教程