ASP.NET Core MVC 支持对使用指定格式或对客户端请求响应的响应数据进行格式设置。
一些操作结果类型特定于特殊格式,例如
JsonResult
和
ContentResult
。 这些操作可以返回始终使用指定格式的结果,这将忽略客户端对不同格式的请求。 例如,返回
JsonResult
将返回 JSON 格式的数据,返回
ContentResult
将返回纯文本格式的字符串数据。
无需操作返回任意特定类型。 ASP.NET Core 支持任何对象返回值。 对于返回非
IActionResult
类型对象的操作的结果,将使用相应的
IOutputFormatter
实现来对这些结果进行序列化。 有关详细信息,请参阅
ASP.NET Core Web API 中的控制器操作返回类型
。
默认情况下,内置的帮助程序方法
ControllerBase.Ok
返回 JSON 格式的数据:
[HttpGet]
public IActionResult Get() =>
Ok(_todoItemStore.GetList());
示例代码将返回 todo 项的列表。 在 F12 浏览器开发人员工具或
Postman
中,上述代码将显示:
包含 content-type:
application/json; charset=utf-8
的响应标头。
请求标头。 例如
Accept
标头。 上述代码将忽略
Accept
标头。
若要返回纯文本格式数据,请使用
ContentResult
和
Content
帮助程序:
[HttpGet("Version")]
public ContentResult GetVersion() =>
Content("v1.0.0");
在上述代码中,返回的
text/plain
为
Content-Type
。
对于包含多个返回类型的操作,将返回
IActionResult
。 例如,基于操作的结果返回不同的 HTTP 状态代码时。
当客户端指定
Accept 标头
时,会发生内容协商。 ASP.NET Core 使用的默认格式是
JSON
。 内容协商有以下特点:
由
ObjectResult
实现。
内置于从帮助程序方法返回的特定于状态代码的操作结果中。 操作结果帮助程序方法基于
ObjectResult
。
返回一个模型类型时,返回类型为
ObjectResult
。
以下操作方法使用
Ok
和
NotFound
帮助程序方法:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
var todo = _todoItemStore.GetById(id);
if (todo is null)
return NotFound();
return Ok(todo);
默认情况下,ASP.NET Core 支持以下媒体类型:
application/json
text/json
text/plain
Fiddler
或
Postman
等工具可以设置
Accept
请求标头,来指定返回格式。
Accept
标头包含服务器支持的类型时,将返回该类型。 下一节将介绍如何添加其他格式化程序。
控制器操作可以返回 POCO(普通旧 CLR 对象)。 返回 POCO 时,运行时自动创建包装该对象的
ObjectResult
。 客户端将获得已格式化和序列化的对象。 若将返回的对象为
null
,将返回
204 No Content
响应。
以下示例返回一个对象类型:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
在上述代码中,对有效 todo 项的请求将返回
200 OK
响应。 对无效 todo 项的请求将返回
204 No Content
响应。
内容协商在
Accept
标头出现在请求中时发生
。 请求包含 Accept 标头时,ASP.NET Core 将执行以下操作:
按首选顺序枚举 Accept 标头中的媒体类型。
尝试找到可以生成某种指定格式的响应的格式化程序。
若未找到可以满足客户端请求的格式化程序,ASP.NET Core 将指定以下操作:
如果
MvcOptions.ReturnHttpNotAcceptable
设为
true
,返回
406 Not Acceptable
,否则 -
尝试找到第一个可以生成响应的格式化程序。
如果没有配置实现所请求格式的格式化程序,那么使用第一个可以设置对象格式的格式化程序。 若请求中没有
Accept
标头:
将使用第一个可以处理对象的格式化程序来将响应序列化。
不执行任何协商。 服务器将决定要返回的格式。
如果 Accept 标头包含
*/*
,则将忽略该标头,除非
RespectBrowserAcceptHeader
在
MvcOptions
上设置为 true。
浏览器和内容协商
与典型的 API 客户端不同的是,Web 浏览器提供
Accept
标头。 Web 浏览器指定多种格式,包括通配符。 默认情况下,当框架检测到请求来自浏览器时,将执行以下操作:
忽略
Accept
标头。
若未另行配置,将使用 JSON 返回内容。
这样,在使用 API 时,各种浏览器中的体验将更加一致。
若要将应用配置为接受浏览器 Accept 标头,请将
RespectBrowserAcceptHeader
属性设置为
true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
options.RespectBrowserAcceptHeader = true;
需要支持额外格式的应用可以添加相应的 NuGet 包并配置支持。 输入和输出的格式化程序不同。
模型绑定
使用输入格式化程序。 格式响应使用输出格式化程序。 有关创建自定义格式化程序的信息,请参阅
自定义格式化程序
。
若要配置使用
XmlSerializer
实现的 XML 格式化程序,请调用
AddXmlSerializerFormatters
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
使用前面的代码时,控制器方法会基于请求的
Accept
标头返回相应的格式。
配置基于
System.Text.Json
的格式化程序
若要配置基于
System.Text.Json
的格式化程序的功能,请使用
Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions
。 以下突出显示的代码配置 PascalCase 格式,而不是默认的 camelCase 格式:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null;
以下操作方法调用
ControllerBase.Problem
来创建
ProblemDetails
响应:
[HttpGet("Error")]
public IActionResult GetError() =>
Problem("Something went wrong.");
ProblemDetails
响应始终为 camelCase 格式,即使应用将格式设置为 PascalCase 也是如此。
ProblemDetails
遵循
RFC 7807
,这将指定为小写。
若要为特定操作配置输出序列化选项,请使用
JsonResult
。 例如:
[HttpGet]
public IActionResult Get() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions
PropertyNamingPolicy = null
默认的 JSON 格式化程序使用
System.Text.Json
。 若要使用基于
Newtonsoft.Json
的格式化程序,请安装
Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 包并在
Program.cs
中进行配置:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
在上述代码中,对
AddNewtonsoftJson
的调用会将以下 Web API、MVC 和 Razor Pages 功能配置为使用
Newtonsoft.Json
:
读取和编写 JSON 的输入和输出格式化程序
JsonResult
JSON 修补程序
IJsonHelper
TempData
某些功能可能不适用于基于
System.Text.Json
的格式化程序,而需要引用基于
Newtonsoft.Json
的格式化程序。 当应用符合以下情况时,请继续使用基于
Newtonsoft.Json
的格式化程序:
使用
Newtonsoft.Json
属性。 例如,
[JsonProperty]
或
[JsonIgnore]
。
自定义序列化设置。
依赖
Newtonsoft.Json
提供的功能。
若要配置基于
Newtonsoft.Json
的格式化程序的功能,请使用
SerializerSettings
:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
若要为特定操作配置输出序列化选项,请使用
JsonResult
。 例如:
[HttpGet]
public IActionResult GetNewtonsoftJson() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings
ContractResolver = new DefaultContractResolver()
应用
[Produces]
筛选器,以限制响应格式。 如同大多
筛选器
,
[Produces]
可以在操作层面、控制器层面或全局范围内应用:
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
上述
[Produces]
筛选器将执行以下操作:
强制控制器中的所有操作返回 POCO(普通旧 CLR 对象)或
ObjectResult
及其派生类型的 JSON 格式响应。
返回 JSON 格式的响应,即使配置了其他格式化程序并且客户端指定了其他格式也是如此。
有关详细信息,请参阅
筛选器
。
一些特例是使用内置格式化程序实现的。 默认情况下,
string
返回类型的格式将设为 text/plain(如果通过
Accept
标头请求则为 text/html)。 可以通过删除
StringOutputFormatter
删除此行为。 格式化程序会从
Program.cs
中删除。 有模型对象返回类型的操作将在返回
null
时返回
204 No Content
。 可以通过删除
HttpNoContentOutputFormatter
删除此行为。 以下代码删除
StringOutputFormatter
和
HttpNoContentOutputFormatter
。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
如果没有
StringOutputFormatter
,则内置 JSON 格式化程序将设置
string
返回类型的格式。 如果删除了内置 JSON 格式化程序并提供了 XML 格式化程序,则 XML 格式化程序将设置
string
返回类型的格式。 否则,
string
返回类型返回
406 Not Acceptable
。
没有
HttpNoContentOutputFormatter
,null 对象将使用配置的格式化程序来进行格式设置。 例如:
JSON 格式化程序返回正文为
null
的响应。
设置属性
xsi:nil="true"
时,XML 格式化程序返回空 XML 元素。
客户端可以在 URL 中请求特定格式,例如:
在查询字符串中,或在路径中。
使用格式特定的文件扩展名,如 .xml 或 .json。
请求路径的映射必须在 API 使用的路由中指定。 例如:
[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
private readonly TodoItemStore _todoItemStore;
public TodoItemsController(TodoItemStore todoItemStore) =>
_todoItemStore = todoItemStore;
[HttpGet("{id:long}.{format?}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
上述路由将允许使用可选文件扩展名来指定请求的格式。
[FormatFilter]
属性检查
RouteData
中格式值是否存在,并在响应创建时将响应格式映射到相应格式化程序。
格式化程序
ASP.NET Core MVC 支持设置响应数据的格式。 可以使用特定格式或响应客户端请求的格式,来设置响应数据的格式。
查看或下载示例代码
(
如何下载
)
一些操作结果类型特定于特殊格式,例如
JsonResult
和
ContentResult
。 操作可以返回使用特定格式设置格式的结果,而不考虑客户端首选项。 例如,返回
JsonResult
将返回 JSON 格式的数据。 返回
ContentResult
或字符串,将返回纯文本格式的字符串数据。
无需操作返回任意特定类型。 ASP.NET Core 支持任何对象返回值。 对于返回非
IActionResult
类型对象的操作的结果,将使用相应的
IOutputFormatter
实现来对这些结果进行序列化。 有关详细信息,请参阅
ASP.NET Core Web API 中的控制器操作返回类型
。
内置的帮助程序方法
Ok
返回 JSON 格式的数据:
// GET: api/authors
[HttpGet]
public ActionResult Get()
return Ok(_authors.List());
示例下载返回作者列表。 在 F12 浏览器开发人员工具或
Postman
中使用上述代码:
将显示包含内容类型的响应标头。
application/json; charset=utf-8
将显示请求标头。 例如
Accept
标头。 上述代码将忽略
Accept
标头。
若要返回纯文本格式数据,请使用
ContentResult
和
Content
帮助程序:
// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
return Content("An API listing authors of docs.asp.net.");
在上述代码中,返回的
text/plain
为
Content-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
。
以下操作方法使用
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
标头出现在请求中时发生
。 请求包含 Accept 标头时,ASP.NET Core 将执行以下操作:
按首选顺序枚举 Accept 标头中的媒体类型。
尝试找到可以生成某种指定格式的响应的格式化程序。
若未找到可以满足客户端请求的格式化程序,ASP.NET Core 将指定以下操作:
如果
MvcOptions.ReturnHttpNotAcceptable
设为
true
,返回
406 Not Acceptable
,否则 -
尝试找到第一个可以生成响应的格式化程序。
如果没有配置实现所请求格式的格式化程序,那么使用第一个可以设置对象格式的格式化程序。 若请求中没有
Accept
标头:
将使用第一个可以处理对象的格式化程序来将响应序列化。
不执行任何协商。 服务器将决定要返回的格式。
如果 Accept 标头包含
*/*
,则将忽略该标头,除非
RespectBrowserAcceptHeader
在
MvcOptions
上设置为 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
需要支持其他格式的应用可以添加相应的 NuGet 包,并配置支持。 输入和输出的格式化程序不同。
模型绑定
使用输入格式化程序。 格式响应使用输出格式化程序。 有关创建自定义格式化程序的信息,请参阅
自定义格式化程序
。
调用
AddXmlSerializerFormatters
来配置使用
XmlSerializer
实现的 XML 格式化程序:
public void ConfigureServices(IServiceCollection services)
services.AddControllers()
.AddXmlSerializerFormatters();
前面的代码将使用
XmlSerializer
将结果序列化。
使用前面的代码时,控制器方法会基于请求的
Accept
标头返回相应的格式。
配置基于
System.Text.Json
的格式化程序
可以使用
Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions
配置基于
System.Text.Json
的格式化程序的功能。 默认格式为 camelCase。 以下突出显示的代码设置 PascalCase 格式:
public void ConfigureServices(IServiceCollection services)
services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null);
以下操作方法调用
ControllerBase.Problem
来创建
ProblemDetails
响应:
[HttpGet("error")]
public IActionResult GetError()
return Problem("Something went wrong!");
通过使用上述代码:
https://localhost:5001/WeatherForecast/temperature
返回 PascalCase。
https://localhost:5001/WeatherForecast/error
返回 camelCase。 错误响应始终为 camelCase 格式,即使应用将格式设置为 PascalCase 也是如此。
ProblemDetails
遵循
RFC 7807
,这将指定为小写
以下代码设置 PascalCase 并添加自定义转换器:
services.AddControllers().AddJsonOptions(options =>
// Use the default property (Pascal) casing.
options.JsonSerializerOptions.PropertyNamingPolicy = null;
// Configure a custom converter.
options.JsonSerializerOptions.Converters.Add(new MyCustomJsonConverter());
可以使用 JsonResult
配置基于每个操作的输出序列化选项。 例如:
public IActionResult Get()
return Json(model, new JsonSerializerOptions
WriteIndented = true,
默认的 JSON 格式化程序基于 System.Text.Json
。 通过安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 包并在 Startup.ConfigureServices
中进行配置可以实现对基于 Newtonsoft.Json
的格式化程序和功能的支持。
public void ConfigureServices(IServiceCollection services)
services.AddControllers()
.AddNewtonsoftJson();
在上述代码中,对 AddNewtonsoftJson
的调用会将以下 Web API、MVC 和 Razor Pages 功能配置为使用 Newtonsoft.Json
:
读取和编写 JSON 的输入和输出格式化程序
JsonResult
JSON 修补程序
IJsonHelper
TempData
某些功能可能不适用于基于 System.Text.Json
的格式化程序,而需要引用基于 Newtonsoft.Json
的格式化程序。 当应用符合以下情况时,请继续使用基于 Newtonsoft.Json
的格式化程序:
使用 Newtonsoft.Json
属性。 例如,[JsonProperty]
或 [JsonIgnore]
。
自定义序列化设置。
依赖 Newtonsoft.Json
提供的功能。
可以使用 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.SerializerSettings.Converters.Add(new MyCustomJsonConverter());
可以使用 JsonResult
配置基于每个操作的输出序列化选项。 例如:
public IActionResult Get()
return Json(model, new JsonSerializerSettings
Formatting = Formatting.Indented,
应用 [Produces]
筛选器,以限制响应格式。 如同大多筛选器,[Produces]
可以在操作层面、控制器层面或全局范围内应用:
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
上述 [Produces]
筛选器将执行以下操作:
强制控制器中的所有操作返回 POCO(普通旧 CLR 对象)或 ObjectResult 及其派生类型的 JSON 格式响应。
若已配置其他格式化程序,并且客户端指定了其他格式,将返回 JSON。
有关详细信息,请参阅筛选器。
一些特例是使用内置格式化程序实现的。 默认情况下,string
返回类型的格式将设为 text/plain(如果通过 Accept
标头请求则为 text/html)。 可以通过删除 StringOutputFormatter 删除此行为。 在 ConfigureServices
方法中删除格式化程序。 有模型对象返回类型的操作将在返回 null
时返回 204 No Content
。 可以通过删除 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>();
如果没有 StringOutputFormatter
,则内置 JSON 格式化程序将设置 string
返回类型的格式。 如果删除了内置 JSON 格式化程序并提供了 XML 格式化程序,则 XML 格式化程序将设置 string
返回类型的格式。 否则,string
返回类型返回 406 Not Acceptable
。
没有 HttpNoContentOutputFormatter
,null 对象将使用配置的格式化程序来进行格式设置。 例如:
JSON 格式化程序返回正文为 null
的响应。
设置属性 xsi:nil="true"
时,XML 格式化程序返回空 XML 元素。
客户端可以在 URL 中请求特定格式,例如:
在查询字符串中,或在路径中。
使用格式特定的文件扩展名,如 .xml 或 .json。
请求路径的映射必须在 API 使用的路由中指定。 例如:
[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
[HttpGet("{id}.{format?}")]
public Product Get(int id)
上述路由将允许指定所请求格式为可选文件扩展名。 [FormatFilter]
属性检查 RouteData
中格式值是否存在,并在响应创建时将响应格式映射到相应格式化程序。
格式化程序
ASP.NET Core MVC 支持对使用指定格式或对客户端请求响应的响应数据进行格式设置。
一些操作结果类型特定于特殊格式,例如 JsonResult 和 ContentResult。 这些操作可以返回始终使用指定格式的结果,这将忽略客户端对不同格式的请求。 例如,返回 JsonResult
将返回 JSON 格式的数据,返回 ContentResult
将返回纯文本格式的字符串数据。
无需操作返回任意特定类型。 ASP.NET Core 支持任何对象返回值。 对于返回非 IActionResult 类型对象的操作的结果,将使用相应的 IOutputFormatter 实现来对这些结果进行序列化。 有关详细信息,请参阅 ASP.NET Core Web API 中的控制器操作返回类型。
默认情况下,内置的帮助程序方法 ControllerBase.Ok 返回 JSON 格式的数据:
[HttpGet]
public IActionResult Get()
=> Ok(_todoItemStore.GetList());
示例代码将返回 todo 项的列表。 在 F12 浏览器开发人员工具或 Postman 中,上述代码将显示:
包含 content-type:application/json; charset=utf-8
的响应标头。
请求标头。 例如 Accept
标头。 上述代码将忽略 Accept
标头。
若要返回纯文本格式数据,请使用 ContentResult 和 Content 帮助程序:
[HttpGet("Version")]
public ContentResult GetVersion()
=> Content("v1.0.0");
在上述代码中,返回的 text/plain
为 Content-Type
。
对于包含多个返回类型的操作,将返回 IActionResult
。 例如,基于操作的结果返回不同的 HTTP 状态代码时。
当客户端指定 Accept 标头时,会发生内容协商。 ASP.NET Core 使用的默认格式是 JSON。 内容协商有以下特点:
由 ObjectResult 实现。
内置于从帮助程序方法返回的特定于状态代码的操作结果中。 操作结果帮助程序方法基于 ObjectResult
。
返回一个模型类型时,返回类型为 ObjectResult
。
以下操作方法使用 Ok
和 NotFound
帮助程序方法:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
var todo = _todoItemStore.GetById(id);
if (todo is null)
return NotFound();
return Ok(todo);
默认情况下,ASP.NET Core 支持以下媒体类型:
application/json
text/json
text/plain
Fiddler 或 Postman 等工具可以设置 Accept
请求标头,来指定返回格式。 Accept
标头包含服务器支持的类型时,将返回该类型。 下一节将介绍如何添加其他格式化程序。
控制器操作可以返回 POCO(普通旧 CLR 对象)。 返回 POCO 时,运行时自动创建包装该对象的 ObjectResult
。 客户端将获得已格式化和序列化的对象。 若将返回的对象为 null
,将返回 204 No Content
响应。
以下示例返回一个对象类型:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
在上述代码中,对有效 todo 项的请求将返回 200 OK
响应。 对无效 todo 项的请求将返回 204 No Content
响应。
内容协商在 Accept
标头出现在请求中时发生。 请求包含 Accept 标头时,ASP.NET Core 将执行以下操作:
按首选顺序枚举 Accept 标头中的媒体类型。
尝试找到可以生成某种指定格式的响应的格式化程序。
若未找到可以满足客户端请求的格式化程序,ASP.NET Core 将指定以下操作:
如果 MvcOptions.ReturnHttpNotAcceptable 设为 true
,返回 406 Not Acceptable
,否则 -
尝试找到第一个可以生成响应的格式化程序。
如果没有配置实现所请求格式的格式化程序,那么使用第一个可以设置对象格式的格式化程序。 若请求中没有 Accept
标头:
将使用第一个可以处理对象的格式化程序来将响应序列化。
不执行任何协商。 服务器将决定要返回的格式。
如果 Accept 标头包含 */*
,则将忽略该标头,除非 RespectBrowserAcceptHeader
在 MvcOptions 上设置为 true。
浏览器和内容协商
与典型的 API 客户端不同的是,Web 浏览器提供 Accept
标头。 Web 浏览器指定多种格式,包括通配符。 默认情况下,当框架检测到请求来自浏览器时,将执行以下操作:
忽略 Accept
标头。
若未另行配置,将使用 JSON 返回内容。
这样,在使用 API 时,各种浏览器中的体验将更加一致。
若要将应用配置为接受浏览器 Accept 标头,请将 RespectBrowserAcceptHeader 属性设置为 true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
options.RespectBrowserAcceptHeader = true;
需要支持额外格式的应用可以添加相应的 NuGet 包并配置支持。 输入和输出的格式化程序不同。 模型绑定使用输入格式化程序。 格式响应使用输出格式化程序。 有关创建自定义格式化程序的信息,请参阅自定义格式化程序。
若要配置使用 XmlSerializer 实现的 XML 格式化程序,请调用 AddXmlSerializerFormatters:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
使用前面的代码时,控制器方法会基于请求的 Accept
标头返回相应的格式。
配置基于 System.Text.Json
的格式化程序
若要配置基于 System.Text.Json
的格式化程序的功能,请使用 Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions。 以下突出显示的代码配置 PascalCase 格式,而不是默认的 camelCase 格式:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null;
若要为特定操作配置输出序列化选项,请使用 JsonResult。 例如:
[HttpGet]
public IActionResult Get()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions { PropertyNamingPolicy = null });
默认的 JSON 格式化程序使用 System.Text.Json
。 若要使用基于 Newtonsoft.Json
的格式化程序,请安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 包并在 Program.cs
中进行配置:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
在上述代码中,对 AddNewtonsoftJson
的调用会将以下 Web API、MVC 和 Razor Pages 功能配置为使用 Newtonsoft.Json
:
读取和编写 JSON 的输入和输出格式化程序
JsonResult
JSON 修补程序
IJsonHelper
TempData
某些功能可能不适用于基于 System.Text.Json
的格式化程序,而需要引用基于 Newtonsoft.Json
的格式化程序。 当应用符合以下情况时,请继续使用基于 Newtonsoft.Json
的格式化程序:
使用 Newtonsoft.Json
属性。 例如,[JsonProperty]
或 [JsonIgnore]
。
自定义序列化设置。
依赖 Newtonsoft.Json
提供的功能。
若要配置基于 Newtonsoft.Json
的格式化程序的功能,请使用 SerializerSettings:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
若要为特定操作配置输出序列化选项,请使用 JsonResult
。 例如:
[HttpGet]
public IActionResult GetNewtonsoftJson()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });
以下操作方法调用 ControllerBase.Problem 来创建 ProblemDetails 响应:
[HttpGet("Error")]
public IActionResult GetError()
=> Problem("Something went wrong.");
ProblemDetails
响应始终为 camelCase 格式,即使应用将格式设置为 PascalCase 也是如此。 ProblemDetails
遵循 RFC 7807,这将指定为小写。
将 [ApiController]
特性应用于控制器类时,控制器会在模型验证失败时创建 ValidationProblemDetails 响应。 此响应包括一个字典,该字典使用模型的属性名称作为错误键(未更改)。 例如,以下模型包含需要验证的单个属性:
public class SampleModel
[Range(1, 10)]
public int Value { get; set; }
默认情况下,当 Value
属性无效时,返回的 ValidationProblemDetails
响应使用错误键 Value
,如以下示例所示:
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-00000000000000000000000000000000-000000000000000-00",
"errors": {
"Value": [
"The field Value must be between 1 and 10."
若要设置用作错误键的属性名称的格式,请将 IMetadataDetailsProvider 的实现添加到 MvcOptions.ModelMetadataDetailsProviders 集合中。 以下示例添加一个基于 System.Text.Json
的实现 SystemTextJsonValidationMetadataProvider
,该实现默认将属性名称格式化为 camelCase:
builder.Services.AddControllers();
builder.Services.Configure<MvcOptions>(options =>
options.ModelMetadataDetailsProviders.Add(
new SystemTextJsonValidationMetadataProvider());
SystemTextJsonValidationMetadataProvider
还在其构造函数中接受 JsonNamingPolicy 的实现,该实现指定用于设置属性名称格式的自定义命名策略。
若要在模型中设置属性的自定义名称,请在属性上使用 [JsonPropertyName] 特性:
public class SampleModel
[Range(1, 10)]
[JsonPropertyName("sampleValue")]
public int Value { get; set; }
当 Value
属性无效时,上述模型返回的 ValidationProblemDetails
响应使用错误键 sampleValue
,如以下示例所示:
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-00000000000000000000000000000000-000000000000000-00",
"errors": {
"sampleValue": [
"The field Value must be between 1 and 10."
若要使用 Newtonsoft.Json
设置 ValidationProblemDetails
响应的格式,请使用 NewtonsoftJsonValidationMetadataProvider
:
builder.Services.AddControllers()
.AddNewtonsoftJson();
builder.Services.Configure<MvcOptions>(options =>
options.ModelMetadataDetailsProviders.Add(
new NewtonsoftJsonValidationMetadataProvider());
默认情况下,NewtonsoftJsonValidationMetadataProvider
将属性名称的格式设置为 camelCase。 NewtonsoftJsonValidationMetadataProvider
还在其构造函数中接受 NamingPolicy
的实现,该实现指定用于设置属性名称格式的自定义命名策略。 若要为模型中的属性设置自定义名称,请使用 [JsonProperty]
特性。
应用 [Produces]
筛选器,以限制响应格式。 如同大多筛选器,[Produces]
可以在操作层面、控制器层面或全局范围内应用:
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
上述 [Produces]
筛选器将执行以下操作:
强制控制器中的所有操作返回 POCO(普通旧 CLR 对象)或 ObjectResult 及其派生类型的 JSON 格式响应。
返回 JSON 格式的响应,即使配置了其他格式化程序并且客户端指定了其他格式也是如此。
有关详细信息,请参阅筛选器。
一些特例是使用内置格式化程序实现的。 默认情况下,string
返回类型的格式将设为 text/plain(如果通过 Accept
标头请求则为 text/html)。 可以通过删除 StringOutputFormatter 删除此行为。 格式化程序会从 Program.cs
中删除。 有模型对象返回类型的操作将在返回 null
时返回 204 No Content
。 可以通过删除 HttpNoContentOutputFormatter 删除此行为。 以下代码删除 StringOutputFormatter
和 HttpNoContentOutputFormatter
。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
如果没有 StringOutputFormatter
,则内置 JSON 格式化程序将设置 string
返回类型的格式。 如果删除了内置 JSON 格式化程序并提供了 XML 格式化程序,则 XML 格式化程序将设置 string
返回类型的格式。 否则,string
返回类型返回 406 Not Acceptable
。
没有 HttpNoContentOutputFormatter
,null 对象将使用配置的格式化程序来进行格式设置。 例如:
JSON 格式化程序返回正文为 null
的响应。
设置属性 xsi:nil="true"
时,XML 格式化程序返回空 XML 元素。
客户端可以在 URL 中请求特定格式,例如:
在查询字符串中,或在路径中。
使用格式特定的文件扩展名,如 .xml 或 .json。
请求路径的映射必须在 API 使用的路由中指定。 例如:
[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
private readonly TodoItemStore _todoItemStore;
public TodoItemsController(TodoItemStore todoItemStore)
=> _todoItemStore = todoItemStore;
[HttpGet("{id:long}.{format?}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
上述路由将允许使用可选文件扩展名来指定请求的格式。 [FormatFilter]
属性检查 RouteData
中格式值是否存在,并在响应创建时将响应格式映射到相应格式化程序。
格式化程序