原文:Formatting Response Data

作者:Steve Smith

翻译:刘怡(AlexLEWIS)

校对:许登洋(Seay)

ASP.NET Core MVC 内建支持对相应数据(response data)的格式化,用来修正格式或生成客户端指定的格式。

从 GitHub 上查看或下载相关样例 。

特定格式的操作结果

某些操作结果(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)格式化响应数据的更多相关文章

  1. ASP.NET Core 中文文档 第四章 MVC(4.5)测试控制器逻辑

    原文: Testing Controller Logic 作者: Steve Smith 翻译: 姚阿勇(Dr.Yao) 校对: 高嵩(Jack) ASP.NET MVC 应用程序的控制器应当小巧并专 ...

  2. ASP.NET Core 中文文档 第四章 MVC(4.1)Controllers, Actions 和 Action Results

    原文:Controllers, Actions, and Action Results 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:许登洋(Seay) Action 和 acti ...

  3. ASP.NET Core 中文文档 第四章 MVC(4.2)控制器操作的路由

    原文:Routing to Controller Actions 作者:Ryan Nowak.Rick Anderson 翻译:娄宇(Lyrics) 校对:何镇汐.姚阿勇(Dr.Yao) ASP.NE ...

  4. ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍

    原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...

  5. ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入

    原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...

  6. ASP.NET Core 中文文档 第四章 MVC(4.6)Areas(区域)

    原文:Areas 作者:Dhananjay Kumar 和 Rick Anderson 翻译:耿晓亮(Blue) 校对:许登洋(Seay) Areas 是 ASP.NET MVC 用来将相关功能组织成 ...

  7. ASP.NET Core 中文文档 第四章 MVC(4.4)依赖注入和控制器

    原文: Dependency Injection and Controllers 作者: Steve Smith 翻译: 刘浩杨 校对: 孟帅洋(书缘) ASP.NET Core MVC 控制器应通过 ...

  8. ASP.NET Core 中文文档 第四章 MVC(3.9)视图组件

    作者: Rick Anderson 翻译: 娄宇(Lyrics) 校对: 高嵩 章节: 介绍视图组件 创建视图组件 调用视图组件 演练:创建一个简单的视图组件 附加的资源 查看或下载示例代码 介绍视图 ...

  9. ASP.NET Core 中文文档 第四章 MVC(3.7 )局部视图(partial)

    原文:Partial Views 作者:Steve Smith 翻译:张海龙(jiechen).刘怡(AlexLEWIS) 校对:许登洋(Seay).何镇汐.魏美娟(初见) ASP.NET Core ...

  10. ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览

    原文:Overview of ASP.NET Core MVC 作者:Steve Smith 翻译:张海龙(jiechen) 校对:高嵩 ASP.NET Core MVC 是使用模型-视图-控制器(M ...

随机推荐

  1. .NetCore MVC中的路由(1)路由配置基础

    .NetCore MVC中的路由(1)路由配置基础 0x00 路由在MVC中起到的作用 前段时间一直忙于别的事情,终于搞定了继续学习.NetCore.这次学习的主题是MVC中的路由.路由是所有MVC框 ...

  2. MVVM设计模式和WPF中的实现(四)事件绑定

    MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  3. Java 征途:行者的地图

    前段时间应因缘梳理了下自己的 Java 知识体系, 成文一篇望能帮到即将走进或正在 Java 世界跋涉的程序员们. 第一张,基础图 大约在 2003 年我开始知道 Java 的(当时还在用 Delph ...

  4. Windows平台分布式架构实践 - 负载均衡

    概述 最近.NET的世界开始闹腾了,微软官方终于加入到了对.NET跨平台的支持,并且在不久的将来,我们在VS里面写的代码可能就可以通过Mono直接在Linux和Mac上运行.那么大家(开发者和企业)为 ...

  5. JS继承类相关试题

    题目一: //有关于原型继承的代码如下:function Person(name) {   this.name = name;}Person.prototype = {     getName : f ...

  6. Mysql存储引擎比较

    Mysql作为一个开源的免费数据库,在平时项目当中会经常使用到,而在项目当中我们的着重点一般在设计使用数据库上而非mysql本身上,所以在提到mysql的存储引擎时,一般都不曾知道,这里经过网上相关文 ...

  7. python 3.5 成功安装 scrapy 的步骤

    http://www.cnblogs.com/hhh5460/p/5814275.html

  8. PHP设计模式(二)工厂方法模式(Factory Method For PHP)

    简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...

  9. Java企业实训 - 01 - Java前奏

    前言: 虽然个人专攻.NET方向,不过由于个人是干教育行业的,方方面面的东西,不能说都必须精通,但肯定多少都会涉及到. 一个菜鸟学员,从啥都不会,经过一步步学习,最后到企业上手掌管一个模块甚至一个项目 ...

  10. php安装threads多线程扩展

    php5.3或以上,且为线程安全版本.apache和php使用的编译器必须一致.通过phpinfo()查看Thread Safety为enabled则为线程安全版.通过phpinfo()查看Compi ...