ASP.NET Core 中文文档 第四章 MVC(2.3)格式化响应数据
原文:Formatting Response Data
作者:Steve Smith
翻译:刘怡(AlexLEWIS)
校对:许登洋(Seay)
ASP.NET Core MVC 内建支持对相应数据(response data)的格式化,用来修正格式或生成客户端指定的格式。
特定格式的操作结果
某些操作结果(Action result)的类型是指定的特定格式,比如 JsonResult 或 ContentResult。Action 可以返回格式化为特定方式的具体结果。比如返回 JsonResult 将返回 JSON 格式化数据,而不是客户端要求的的格式。同样地,返回 ContentResult 将返回纯文本格式的字符串数据(就像是简单第返回一个字符串那样)。
提示
Action 并不强制要求返回一个特定的类型,MVC 支持任何对象作为返回值。如果 Action 返回的是IActionResult的某个实现并且控制器继承自Controller,那么开发人员就可以使用很多辅助方法(对应地就会有很多选择)。从 Action 返回的结果如果不是IActionResult类型的对象的话将使用适当的IOutputFormatter实现序列化。
若要从继承了 Controller 基类的控制器返回指定格式的数据,可以使用内置的辅助方法 Json
来返回 JSON 格式,使用 Content 来返回纯文本。此时你的 Action 方法的返回类型就必须是指定的结果类型(如 JsonResult)或 IActionResult。
返回 JSON 格式的数据:
// GET: api/authors
[HttpGet]
public JsonResult Get()
{
return Json(_authorRepository.List());
}
这个操作(Action)将返回的响应样本:

注意,响应的内容类型是 application/json,它同时显示在网络请求列表中和响应的头节点中。另外还要注意,由浏览器(比如 Microsoft Edge)提交的请求头中 Accept 头的选择列表。当前的技术方案是忽略这个头信息,下面将具体讨论。
要返回纯文本格式的数据,请使用 ContentResult 以及 Content 辅助方法:
// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
return Content("An API listing authors of docs.asp.net.");
}
该 Action 的响应:

注意在此情况下, Content-Type 将返回 test/plain。你也可以通过一个字符串来实现响应这一相同行为:
// GET api/authors/version
[HttpGet("version")]
public string Version()
{
return "Version 1.0.0";
}
小技巧
对于将返回不同类型或选项的复杂操作(non-trivial actions)(比如根据操作的结果不同返回不同 HTTP 状态码),那么请使用IActionResult作为返回类型。
内容协商
内容协商(简写为 conneg)是指:当客户端在 Accept 头 中指定接受要求时会发生的过程。ASP.NET Core MVC 默认格式使用的是 JSON。内容协商由 ObjectResult 实现,它还内置了从辅助方法(它们尽数基于 ObjectResult)为指定的 Action 结果返回状态码的功能。你也可以返回一个模型类型(你自行定义的数据传输类),框架将自动为你将其包装在 ObjectResult 内。
下面的 Action 方法使用 Ok 和 NotFound 两种辅助方法:
// 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 格式的响应。你可以使用像 Fiddler这样的工具来创建包含 Accept 头的、并且指定另一种格式的请求。在这种情况下,如果服务器具有创建请求中指定格式的 formatter,那么该结果将按客户端所选的格式返回。

在上面的截图中,Fiddler 的 Composer 标签可用于生成请求,并指定 Accept: application/xml。默认情况下,ASP.NET Core MVC 只支持 JSON,所以即使是指定了另一种格式,返回的依旧是 JSON 格式。你可以在下一节中了解到如何增加其它格式。
控制器的 Action 可以返回 POCO(Plain Old CLR Objects),此时 ASP.NET Core MVC 会自动创建ObjectResult 并将该对象进行包装。客户端将获得经序列化后的对象(默认是 JSON 格式,当然你也可以自己配置 XML 或其它格式)、如果对象返回的是 null,那么框架将返回 204 No Content 响应。
返回对象类型:
// GET api/authors/ardalis
[HttpGet("{alias}")]
public Author Get(string alias)
{
return _authorRepository.GetByAlias(alias);
}
在本例中,有效的作者别名的请求将收到 200 OK 响应(带着作者的数据),而无效别名将收到 204 No Content 响应。截图中分别显示了 XML 和 JSON 的响应。
内容协商过程
内容协商只在当 Accept 头出现在请求中时才会发生。当请求包含 Accept 头时,框架将按优先级的顺序枚举媒体类型(media types)并尝试寻找能生产出 Accept 头中指定格式(中的一种)的格式化程序。如果找到可以满足客户端请求的格式化程序,框架将尝试寻找第一个能生产响应的格式化程序(除非开发人员已经在 MvcOptions 中配置返回 406 Not Acceptable 响应)。如果请求指定的格式是 XML,但 XML 格式化程序并没有被配置,那么将使用 JSON 格式化程序。更通常地来讲,如果没有配置任何可以提供所请求的格式的格式化程序,那么将使用第一个格式化程序来格式化对象。如果没有给定头,那么所返回的对象将使用第一个格式化程序来序列化。在这种情况下并没有发生内容协商——其实是由服务器来决定使用哪种格式来格式化对象。
提示
如果 Accept 头中包含/,那么 Header 将被忽略,除非MvcOptions的RespectBrowserAcceptHeader设置为 true。
浏览器和内容协商
与其它 API 客户端不同,Web 浏览器一般都会在请求中包含 Accept 头,其中使用通配符(wildcards)。默认情况下,当框架检测到请求来自浏览器,它就会忽略 Accept 头并返回应用程序配置的默认格式(如果没有另行安排,则默认为 JSON 格式)。这样一来,当使用不同的浏览器消费 API 时提供一致的体验。
如果你希望你的应用程序优先考虑浏览器的 Accept 头,你可以在 MVC 的配置中进行相关配置,具体来讲是在 Startup.cs 的 ConfigureServices 方法中将 RespectBrowserAcceptHeader 设置为 true。
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
}
配置格式化程序
如果你的应用程序需要支持默认的 JSON 之外的格式,那么你需要在 project.json 文件中添加这些额外的依赖项,并配置 MVC 来支持它们。输入和输出的格式是可以隔离的。输入格式通过使用模型绑定,输出格式通过使用格式化响应。你也可以配置 自定义格式化。
添加对 XML 格式的支持
为增加对 XML 格式的支持,需要在 project.json 的 dependencies 列表中增加“Microsoft.AspNetCore.Mvc.Formatters.Xml”包。
在 Startup.cs 的 MVC 配置中添加 XmlSerializerFormatters:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddXmlSerializerFormatters();
services.AddScoped<IAuthorRepository, AuthorRepository>();
}
或者你可以只添加输出格式:
services.AddMvc(options =>
{
options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
});
这两种方法都将使用 System.Xml.Serialization.XmlSerializer 序列化结果。如果你愿意,你可以通过添加其它相关格式来使用 System.Runtime.Serialization.DataContractSerializer 。
services.AddMvc(options =>
{
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
});
一旦你添加了对 XML 格式的支持,你的控制器方法就可以根据 Accept 头信息来返回相应的格式了,就像下面这个 Fiddler 的演示:

你可以在 Inspectors 标签下看到,原始 GET 请求设置了 Accept: application/xml 头,在响应面板中显示 Content-Type: application/xml 头,并且有一个已经被序列化为 XML 格式的 Author 对象。
使用 Composer 面板可以修改请求,把 Accept 头改为 application/json,然后执行这个请求,此时将获得一个格式化为 JSON 格式的响应:

在这个截图中,你可以发现请求报文中的 Accept: application/json 头以及与之相同的响应 Content-Type 。同时 Author 对象也序列化为 JSON 格式后出现在响应报文中。
强制特定格式化
若是你想为某个 action 限制响应格式,可以使用 [Produces] 过滤器。[Produces] 过滤器可以为这个控制器或 Action 指定响应格式。就像大多数 过滤器 那样,这一过滤器可应用于 Action、控制器,甚至全局范围。
[Produces("application/json")]
public class AuthorsController
[Produces] 过滤器会强制要求所有 AuthorsController 内的 Action 返回 JSON 格式的响应,即使其它格式化程序已经在应用程序中配置了、且客户端也通过 Accept 头指明要返回 JSON 之外的其他可用格式。更多请查阅 过滤器 ,包括如何在全局范围应用过滤器。
特例格式化程序
一些特殊情况下使用的是内建的格式化实现。默认情况下,返回类型为 string 将格式化为 text/plain (如果通过 Accept 头的话则是 text/html )。这种行为可以通过移除TextOutputFormatter 来改变。如果你如下例代码这般在 Startup.cs 的 Configure 方法中移除了HttpNoContentOutputFormatter,那么当你某个返回类型为模型对象的 Action 返回了 null 时将返回 204 No Content 响应。下列代码移除了 TextOutputFormatter 和 HttpNoContentOutputFormatter 。
services.AddMvc(options =>
{
options.OutputFormatters.RemoveType<TextOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
如果没有 TextOutputFormatter,返回类型为 string 的操作将返回 406 Not Acceptable。此时请注意,如果存在 XML 格式化程序,此时将格式化该响应结果。
如果没有 HttpNoContentOutputFormatter,空对象将使用配置的格式进行格式化。比如 JSON 格式将简单的返回主体信息为 null 的响应,而 XML 格式将返回一个空的带有 xsi:nil="true" 特性集的 XML 元素。
响应格式 URL 映射
客户端可以在 URL 中请求特定的格式,比如在请求字符串(query string)或路径(path)中,或者索性使用特定格式的文件扩展名(比如 .xml 或 .json)。从请求路径中进行映射的话需要在 API 所使用的路由中进行指定,比如:
[FormatFilter]
public class ProductsController
{
[Route("[controller]/[action]/{id}.{format?}")]
public Product GetById(int id)
这一路由配置将允许使用可选的文件扩展名来指定格式。[FormatFilter] 特性将在 RouteData 中检查该格式的值是否存在,并在创建响应时将响应数据映射为适当的格式。
| 路由 | 格式化 |
|---|---|
/products/GetById/5 |
默认输出格式 |
/products/GetById/5.json |
JSON 格式(如果配置了的话) |
/products/GetById/5.xml |
XML 格式(如果配置了的话) |
ASP.NET Core 中文文档 第四章 MVC(2.3)格式化响应数据的更多相关文章
- ASP.NET Core 中文文档 第四章 MVC(4.5)测试控制器逻辑
原文: Testing Controller Logic 作者: Steve Smith 翻译: 姚阿勇(Dr.Yao) 校对: 高嵩(Jack) ASP.NET MVC 应用程序的控制器应当小巧并专 ...
- ASP.NET Core 中文文档 第四章 MVC(4.1)Controllers, Actions 和 Action Results
原文:Controllers, Actions, and Action Results 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:许登洋(Seay) Action 和 acti ...
- ASP.NET Core 中文文档 第四章 MVC(4.2)控制器操作的路由
原文:Routing to Controller Actions 作者:Ryan Nowak.Rick Anderson 翻译:娄宇(Lyrics) 校对:何镇汐.姚阿勇(Dr.Yao) ASP.NE ...
- ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍
原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...
- ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入
原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...
- ASP.NET Core 中文文档 第四章 MVC(4.6)Areas(区域)
原文:Areas 作者:Dhananjay Kumar 和 Rick Anderson 翻译:耿晓亮(Blue) 校对:许登洋(Seay) Areas 是 ASP.NET MVC 用来将相关功能组织成 ...
- ASP.NET Core 中文文档 第四章 MVC(4.4)依赖注入和控制器
原文: Dependency Injection and Controllers 作者: Steve Smith 翻译: 刘浩杨 校对: 孟帅洋(书缘) ASP.NET Core MVC 控制器应通过 ...
- ASP.NET Core 中文文档 第四章 MVC(3.9)视图组件
作者: Rick Anderson 翻译: 娄宇(Lyrics) 校对: 高嵩 章节: 介绍视图组件 创建视图组件 调用视图组件 演练:创建一个简单的视图组件 附加的资源 查看或下载示例代码 介绍视图 ...
- ASP.NET Core 中文文档 第四章 MVC(3.7 )局部视图(partial)
原文:Partial Views 作者:Steve Smith 翻译:张海龙(jiechen).刘怡(AlexLEWIS) 校对:许登洋(Seay).何镇汐.魏美娟(初见) ASP.NET Core ...
- ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览
原文:Overview of ASP.NET Core MVC 作者:Steve Smith 翻译:张海龙(jiechen) 校对:高嵩 ASP.NET Core MVC 是使用模型-视图-控制器(M ...
随机推荐
- java head space/ java.lang.OutOfMemoryError: Java heap space内存溢出
上一篇JMX/JConsole调试本地还可以在centos6.5 服务器上进行监控有个问题端口只开放22那么设置的9998端口 你怎么都连不上怎么监控?(如果大神知道还望指点,个人见解) 线上项目出现 ...
- JavaScript var关键字、变量的状态、异常处理、命名规范等介绍
本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...
- 猖獗的假新闻:2017年1月1日起iOS的APP必须使用HTTPS
一.假新闻如此猖獗 刚才一位老同事 打电话问:我们公司还是用的HTTP,马上就到2017年了,提交AppStore会被拒绝,怎么办? 公司里已经有很多人问过这个问题,回答一下: HTTP还是可以正常提 ...
- Xamarin+Prism开发详解二:Xaml文件如何简单绑定Resources资源文件内容
我们知道在UWP里面有Resources文件xxx.resx,在Android里面有String.Xml文件等.那跨平台如何统一这些类别不一的资源文件以及Xaml设计文件如何绑定这些资源?应用支持多国 ...
- 【基于WinForm+Access局域网共享数据库的项目总结】之篇一:WinForm开发总体概述与技术实现
篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...
- springMVC初探--环境搭建和第一个HelloWorld简单项目
注:此篇为学习springMVC时,做的笔记整理. MVC框架要做哪些事情? a,将url映射到java类,或者java类的方法上 b,封装用户提交的数据 c,处理请求->调用相关的业务处理—& ...
- 微信开发 :WeixinPayInfoCollection尚未注册Mch 问题解决
在使用开源项目 SENPARC.WEIXIN SDK 调用微信支付接口的时候出现了WeixinPayInfoCollection尚未注册Mch,这个问题. 最后地解决方案是: 我这个傻逼忘了在全局Gl ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
- 【iOS10 SpeechRecognition】语音识别 现说现译的最佳实践
首先想强调一下“语音识别”四个字字面意义上的需求:用户说话然后马上把用户说的话转成文字显示!,这才是开发者真正需要的功能. 做需求之前其实是先谷歌百度一下看有没有造好的轮子直接用,结果真的很呵呵,都是 ...
- SQLServer2005创建定时作业任务
SQLServer定时作业任务:即数据库自动按照定时执行的作业任务,具有周期性不需要人工干预的特点 创建步骤:(使用最高权限的账户登录--sa) 一.启动SQL Server代理(SQL Server ...