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 ...
随机推荐
- URL安全的Base64编码
Base64编码可用于在HTTP环境下传递较长的标识信息.在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式.此时,采用Base64编码不仅比较简短,同时也具有不可 ...
- 你知道C#中的Lambda表达式的演化过程吗?
那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...
- [译]ZOOKEEPER RECIPES-Leader Election
选主 使用ZooKeeper选主的一个简单方法是,在创建znode时使用Sequence和Ephemeral标志.主要思想是,使用一个znode,比如"/election",每个客 ...
- [APUE]文件和目录(下)
一.mkdir和rmdir函数 #include <sys/types.h> #include <sys/stat.h> int mkdir(const char *pathn ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- Kooboo CMS技术文档之二:Kooboo CMS的安装步骤
在IIS上安装Kooboo CMS Kooboo CMS安装之后 安装的常见问题 1. 在IIS上安装Kooboo CMS Kooboo CMS部署到正式环境相当简单,安装过程是一个普通MVC站点在I ...
- 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇一:WPF常用知识以及本项目设计总结
篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...
- C#~异步编程再续~await与async引起的w3wp.exe崩溃-问题友好的解决
返回目录 关于死锁的原因 理解该死锁的原因在于理解await 处理contexts的方式,默认的,当一个未完成的Task 被await的时候,当前的上下文将在该Task完成的时候重新获得并继续执行剩余 ...
- VC中的MFC到底是什么?
1. 微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API ...
- BPM流程中心解决方案分享
一.需求分析 在过去办公自动化的浪潮中,很多企业已经实施了OA流程,但随着客户的发展和对流程管理的越来越重视, 客户对流程应用需求越来越深 入,您可能面临以下需求: 1.流程功能不能满足需求,包括流程 ...