- 设置 ASP.NET Core Web API 中响应数据的格式Format response data in ASP.NET Core Web API
- 特定于格式的操作结果Format-specific Action Results
- 内容协商Content negotiation
- Accept 标头The Accept header
- 浏览器和内容协商Browsers and content negotiation
- 配置格式化程序Configure formatters
- 添加 XML 格式支持Add XML format support
- 配置基于 System.Text.Json 的格式化程序Configure System.Text.Json-based formatters
- 添加基于 Newtonsoft.Json 的 JSON 格式支持Add Newtonsoft.Json-based JSON format support
- 添加 XML 格式支持Add XML format support
- 指定格式Specify a format
- 特例格式化程序Special case formatters
- 响应格式 URL 映射Response format URL mappings
设置 ASP.NET Core Web API 中响应数据的格式Format response data in ASP.NET Core Web API
本文内容
作者:Rick Anderson 和 Steve Smith
ASP.NET Core MVC 支持设置响应数据的格式。可以使用特定格式或响应客户端请求的格式,来设置响应数据的格式。
特定于格式的操作结果Format-specific Action Results
一些操作结果类型特定于特殊格式,例如 JsonResult 和 ContentResult。操作可以返回使用特定格式设置格式的结果,而不考虑客户端首选项。例如,返回 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
标头。
若要返回纯文本格式数据,请使用 Content 和 Content 帮助程序:
// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
return Content("An API listing authors of docs.asp.net.");
}
在上述代码中,返回的 Content-Type
为 text/plain
。返回字符串,将提供 Content-Type
类型的 text/plain
:
// GET api/authors/version
[HttpGet("version")]
public string Version()
{
return "Version 1.0.0";
}
对于包含多个返回类型的操作,将返回 IActionResult
。例如,基于执行的操作的结果返回不同的 HTTP 状态代码。
内容协商Content negotiation
当客户端指定 Accept 标头时,会发生内容协商。ASP.NET Core 使用的默认格式是 JSON。内容协商有以下特点:
- 由 ObjectResult 实现。
- 内置于从帮助程序方法返回的特定于状态代码的操作结果中。操作结果帮助程序方法基于
ObjectResult
。
返回模型类型后,返回类型为 ObjectResult
。
以下操作方法使用 Ok
和 NotFound
帮助程序方法:
// 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/json
、text/json
和 text/plain
媒体类型。Fiddler 或 Postman 等工具可以设置 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 标头The Accept header
内容协商在 标头出现在请求中时发生Accept
。请求包含 Accept 标头时,ASP.NET Core 将执行以下操作:
- 按首选顺序枚举 Accept 标头中的媒体类型。
- 尝试找到可以生成某种指定格式的响应的格式化程序。
若未找到可以满足客户端请求的格式化程序,ASP.NET Core 将指定以下操作:
- 已设置
406 Not Acceptable
时,将返回 MvcOptions,或者 - 尝试找到第一个可以生成响应的格式化程序。
如果没有配置实现所请求格式的格式化程序,那么使用第一个可以设置对象格式的格式化程序。若请求中没有 Accept
标头:
- 将使用第一个可以处理对象的格式化程序来将响应序列化。
- 不执行任何协商。服务器将决定要返回的格式。
如果 Accept 标头包含 /
,则将忽略该标头,除非 RespectBrowserAcceptHeader
在 MvcOptions 上设置为 true。
浏览器和内容协商Browsers and content negotiation
与典型的 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);
}
配置格式化程序Configure formatters
需要支持其他格式的应用可以添加相应的 NuGet 包,并配置支持。输入和输出的格式化程序不同。模型绑定使用输入格式化程序。格式响应使用输出格式化程序。有关创建自定义格式化程序的信息,请参阅自定义格式化程序。
添加 XML 格式支持Add XML format support
调用 XmlSerializer 来配置使用 AddXmlSerializerFormatters 实现的 XML 格式化程序:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddXmlSerializerFormatters();
}
前面的代码将使用 XmlSerializer
将结果序列化。
使用前面的代码时,控制器方法会基于请求的 Accept
标头返回相应的格式。
配置基于 System.Text.Json 的格式化程序Configure System.Text.Json-based formatters
可以使用 System.Text.Json
配置基于 Microsoft.AspNetCore.Mvc.JsonOptions.SerializerOptions
的格式化程序的功能。
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 格式支持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.Json
Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet 包并在 中配置可以支持基于 Startup.ConfigureServices
的格式化程序和功能。
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
接受特定于JsonSerializerSettings
的Newtonsoft.Json
的实例。 - 生成 OpenAPI 文档。
可以使用 Newtonsoft.Json
配置基于 Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings
的格式化程序的功能:
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 格式支持Add XML format support
XML 格式需要 Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet 包。
调用 XmlSerializer 来配置使用 AddXmlSerializerFormatters 实现的 XML 格式化程序:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddXmlSerializerFormatters();
}
前面的代码将使用 XmlSerializer
将结果序列化。
使用前面的代码时,控制器方法应基于请求的 Accept
标头返回相应的格式。
指定格式Specify a format
应用 [Produces]
筛选器,以限制响应格式。如同大多筛选器,[Produces]
可以在操作层面、控制器层面或全局范围内应用:
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{
上述 [Produces]
筛选器将执行以下操作:
- 强制控制器内的所有操作返回 JSON 格式的响应。
- 若已配置其他格式化程序,并且客户端指定了其他格式,将返回 JSON。
有关详细信息,请参阅筛选器。
特例格式化程序Special case formatters
一些特例是使用内置格式化程序实现的。默认情况下,string
返回类型的格式将设为 text/plain(如果通过 标头请求则为 text/html) Accept
。可以通过删除 StringOutputFormatter 删除此行为。在 ConfigureServices
方法中删除格式化程序。有模型对象返回类型的操作将在返回 204 No Content
时返回 null
。可以通过删除 HttpNoContentOutputFormatter 删除此行为。以下代码删除 StringOutputFormatter
和 HttpNoContentOutputFormatter
。
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 映射Response format URL mappings
客户端可以在 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 格式化程序(如配置) |