在上一篇文章《路由其实也可以很简单》,我们解决了路由问题,这篇文章,我们来研究剩下的另一个问题,为何我们的方法返回的是一个列表,输出到客户端的时候,变成json呢,大家应该还记得我们上一篇文章ProductsController的代码:

using ProductsApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Http; namespace ProductsApp.Controllers
{
public class ProductsController : ApiController
{
Product[] products = new Product[]
{
new Product { Id = , Name = "Tomato Soup", Category = "Groceries", Price = },
new Product { Id = , Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = , Name = "Hammer", Category = "Hardware", Price = 16.99M }
}; public IEnumerable<Product> GetAllProducts()
{
return products;
} public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
}
}

  在使用默认的约定的路由时,我们输入地址:http://localhost:1111/Products,结果返回的是json字符串。

  如果大家有ashx的开发经验,应该知道,如果我们是用ashx开发接口,我们可以指定返回的MIME类型,如: 

        public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
}

  但我们调用GetAllProducts()时,并未指定返回的类型。既然客户端输出json了,那就是说webapi在后台帮我们做了一些事情。

  找到这篇介绍MIME类型的文章时,就有大致的头绪了。

  上面这篇文章,我们可以了解到,当客户端发送一个http请求的时候,它可以包括一个Accept标头和正文。Accept标头指明客户端想要服务器端返回哪种MIME类型。MIME类型包括:text/html,image/png,application/json等。MIME类型决定了WebAPI如何序列化和反序列化http的正文(body)。WebAPI内置了XML,JSON,BSON和form-urlencoded data四种格式的支持。原来服务端返回什么,是由客户端的请求决定的!

  我们使用PostMan尝试增加Accept标头,MIME类型为application/xml。

  

  可以看到,返回的果然就是XML。但是,还记得我们默认的请求是没有指定MIME类型的,疑问还没解决,只好继续查下去。

  答案就在这一篇文章中。当客户端发起http请求时,Accept标头,远比我们想象的复杂,例如,有可能是这样的:

Accept: application/json, application/xml; q=0.9, */*; q=0.1

  其中,q是权重因子,0<=q<=1,没有指定的时候,默认值是1。例如上面的application/json,没有指定q值,所以默认是1,相当于application/json;q=1。后面的application/xml,q是0.9,其他*/*是0.1,所以返回次序应该是application/json>application/xml.>*/*。

  实际的情况可能更复杂,甚至是可以没有Accept,这时,WebApi就会检查http请求的body,如果body中包含有json格式的数据,那么WebApi可能就会返回json格式的数据。这仅仅是其中一个例子,总之WebApi自有一套匹配最合适的formatter的算法。

  简而言之,当发起http请求后,WebApi将会根据传入的http和管道上的formatter进行匹配,得到最适合的formatter。如果一直都找不到适合的formatter,那么,WebAPI会选出第一个能序列化输出对象的formatter进行序列化输出。所以,即使我们明确指定了http请求的MIME对象,也不一定能得到对应的输出类型,因为也要取决于WebApi有没有适合的formatter。例如,我们将accept头的application/xml 改为 application/bson,我们发现,返回的依然是json格式的数据,因为WebApi上并没有注册bson格式的formatter。WebApi只好选择第一个能将结果对象序列化的formatter进行序列化输出,这里,就是使用了json formatter了。

  我们打开WebApiConfig.cs文件,增加一行代码,添加对bson格式的支持:

    public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
); //注册bson formatter
config.Formatters.Add(new BsonMediaTypeFormatter()); }
}

  重新生成一下,然后使用PostMan访问,得到以下结果:

  

  可见,新注册的formatter生效了。关于bson,大家可参考https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/bson-support-in-web-api-21

  但是,我们还是建议大家使用http请求的时候,带有明确的MIME类型,而且这个MIME类型不是乱指定的(例如,你明知他会返回json格式,你硬指定MIME类型是text/html),这样,可以尽量避免WebApi再去检查请求的body,性能上来说,应该会快一点。

  于是,有的童鞋自然想到,强制所有输出都是json格式。这可以说,也是一种风格吧。其实作为开发接口的人员,应该对接口十分熟悉,因此,在接口文档清晰指出,Accept标头可以使用哪几种MIME类型即可,并不一定硬要强制所有输出都是json。这样,输出什么类型的数据,就可以由客户端请求自行决定了。

 

输出的数据格式是如何决定的-------Asp.net WebAPI学习笔记(二)的更多相关文章

  1. 路由其实也可以很简单-------Asp.net WebAPI学习笔记(一) ASP.NET WebApi技术从入门到实战演练 C#面向服务WebService从入门到精通 DataTable与List<T>相互转换

    路由其实也可以很简单-------Asp.net WebAPI学习笔记(一)   MVC也好,WebAPI也好,据我所知,有部分人是因为复杂的路由,而不想去学的.曾经见过一位程序猿,在他MVC程序中, ...

  2. 路由其实也可以很简单-------Asp.net WebAPI学习笔记(一)

    MVC也好,WebAPI也好,据我所知,有部分人是因为复杂的路由,而不想去学的.曾经见过一位程序猿,在他MVC程序中,一切皆路由,url中是完全拒绝"?"和“&”.对此,我 ...

  3. [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参

    [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参 本文转自:http://www.cnblogs.com/babycool/p/3922738.html ASP.NET MVC学习系 ...

  4. Asp.Net Core WebApi学习笔记(四)-- Middleware

    Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...

  5. ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现

    ASP.NET MVC 学习笔记-2.Razor语法   1.         表达式 表达式必须跟在“@”符号之后, 2.         代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...

  6. [ASP.NET MVC] ASP.NET Identity学习笔记 - 原始码下载、ID型别差异

    [ASP.NET MVC] ASP.NET Identity学习笔记 - 原始码下载.ID型别差异 原始码下载 ASP.NET Identity是微软所贡献的开源项目,用来提供ASP.NET的验证.授 ...

  7. ASP.NET MVC学习笔记-----Filter2

    ASP.NET MVC学习笔记-----Filter(2) 接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用 ...

  8. ASP.NET MVC学习笔记-----Filter

    ASP.NET MVC学习笔记-----Filter(1) Filter类型 接口 MVC的默认实现 Description Authorization IAuthorizationFilter Au ...

  9. ASP.NET MVC学习笔记-----Filter(2)

    接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用,它需要实现IActionFilter接口: public ...

随机推荐

  1. c++智能指针(1)

    根据muduo开源库作者陈硕的一些文章.对于多线程下C++编程提出了一些观点.主要是多线程下对象的销毁比较困难,但是由于多线程下,mutext是无法保护析构的.而后提出了智能指针的方案并对使用该指针会 ...

  2. 移动端300ms延迟由来及解决方案

    1.300ms延迟由来 300 毫秒延迟的主要原因是解决双击缩放(double tap to zoom).双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页 ...

  3. Python3实战系列之二(获取印度售后数据项目)

    问题:续接上一篇.说干咱就干呀,勤勤恳恳写程序呀! 目标:安装python和pycharm.要编写并运行python程序就需要电脑有开发工具和运行环境,所以此篇就是安装编辑和运行python程序的软件 ...

  4. js jquery 取得周月年时间

    function formatDate(date) { var myyear = date.getFullYear(); var mymonth = date.getMonth() + 1; var ...

  5. Java SE学习【三】——JDBC

    最近学到了数据库与java的jdbc方面,还有个DAO模式,写一下自己的理解,后期有什么不对的再改. 一.数据库三范式的理解 记得以前上课时,也上了一学期的“数据库系统原理”,给我们上课的老师算是渣渣 ...

  6. 利用PHP脚本辅助MySQL数据库管理5-检查异常数据

    <?php $dbi = new DbMysql; $dbi->dbh = 'mysql://root:mysql@127.0.0.1/coffeetest'; $map = array( ...

  7. navicat下创建和执行存储过程

  8. Python之异常处理和socket套接字连接7

    一.异常处理 1)异常处理的使用意义 什么是异常处理 异常是程序发生错误的信号,即程序一旦出错就会立刻产生一个异常,如果该异常没有被处理 那么异常就抛出来,程序的运行也随之终止 异常分为三部分: 异常 ...

  9. Python开课复习-10/16

    import random # random 随机数模块 # print(random.random()) #----float 大于0且小于1之间的小数# print(random.choice([ ...

  10. WebSocket 处理事件

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在 W ...