格式化响应数据

摘要:
Action可以返回格式化为特定方式的具体结果。比如返回JsonResult将返回JSON格式化数据,而不是客户端要求的的格式。若要从继承了Controller基类的控制器返回指定格式的数据,可以使用内置的辅助方法Json来返回JSON格式,使用Content来返回纯文本。result.Any()){returnNotFound;}returnOk;}除非要求返回另一种服务器可以返回的格式,不然将返回JSON格式的响应。截图中分别显示了XML和JSON的响应。如果找到可以满足客户端请求的格式化程序,框架将尝试寻找第一个能生产响应的格式化程序。
格式化响应数据

原文:Formatting Response Data
作者:Steve Smith
翻译:刘怡(AlexLEWIS)
校对:许登洋(Seay)

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

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

特定格式的操作结果

某些操作结果(Action result)的类型是指定的特定格式,比如JsonResultContentResult。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)将返回的响应样本:
json-response

注意,响应的内容类型是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 的响应:
text-response

注意在此情况下,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 方法使用OkNotFound两种辅助方法:

复制代码
// 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

在上面的截图中,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,那么框架将返回204NoContent响应。

返回对象类型:

复制代码
// 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 将被忽略,除非MvcOptionsRespectBrowserAcceptHeader设置为 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 的演示:
xml-response

你可以在 Inspectors 标签下看到,原始 GET 请求设置了Accept:application/xml头,在响应面板中显示Content-Type:application/xml头,并且有一个已经被序列化为 XML 格式的Author对象。

使用 Composer 面板可以修改请求,把Accept头改为application/json,然后执行这个请求,此时将获得一个格式化为 JSON 格式的响应:
json-response-fiddler

在这个截图中,你可以发现请求报文中的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 响应。下列代码移除了TextOutputFormatterHttpNoContentOutputFormatter

复制代码
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.jsonJSON 格式(如果配置了的话)
/products/GetById/5.xmlXML 格式(如果配置了的话)

返回目录

由于水平有限,错漏之处在所难免,欢迎大家批评指正,不胜感激

免责声明:文章转载自《格式化响应数据》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇WinForm 获取指定行列的Valuethinkphp一对多HAS_MANY下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

自动AC机

有更新 注意不是AC自动机! AC自动机是种高级算法,我所介绍的是种作弊方法。 这是一种非常玄学的东西,是用Pascal语言写的用来卡评测机的东西,卡软件BUG,以此来作弊使自己“AC”。 不过只能卡Cena,其他的力有未逮。 现在基本没用了(时代更新太快,bug都修复了) 但也因为它是老古董,所以才又翻出来,收藏一下也是好的,毕竟是当年OIer们的智慧成...

idea配置struts2.5环境

struts2不是struts1的下一代产品,是在struts1和WebWork技术的基础上进行合并后的全新框架,虽然两个名字相似,但是设计思想却有很大的不同。 使用本地的l ib 或者download都可以,这里我使用本地的包,后期比较方便,需要什么包可以直接在本地找到,并拷贝,不需要再去网络上下载 工程命名以及存放位置 新建好工程之后,自行在 WE...

xml中设置button的背景颜色

在画几个设置界面,用到了button控件,对于button空间的背景色在不同状态下的颜色改变方法,做了一下尝试,发现了两种背景颜色改变的方法,就总结了下。 方法一尝试了好多遍才好,要点在于,在selector中android:drawable="@drawable/button_focus"引号中为xml文件,此xml文件为color类型,且在此color...

Servlet(三)

dom4j 元素对象获取指定子元素 element("名字") ServletConfig: 1.在Servlet运行时,需要获取servlet的配置信息 可以使用servletConfig来进行获取 由tomcat创建 在servlet实例化的时候,把servlet的一些配置信息放入ServletConfig对象 2.获取servletConfig:in...

使用阿里云的maven私服的setting.xml, 提高maven项目jar下载速度

下载:  http://files.cnblogs.com/files/007sx/settings.zip 然后替换自己原本maven的配置文件。 如下载失败,可内容替换: <?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/S...

jquery中ajax的dataType属性包括哪几项

参考ajax api文档:http://www.w3school.com.cn/jquery/ajax_ajax.aspdataType类型:String预期服务器返回的数据类型。如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断,比如 XML MIME 类型就被识别为 XML。在 1.4 中,JSON 就会生成一个 JavaSc...