在上一篇文章《路由其实也可以很简单》,我们解决了路由问题,这篇文章,我们来研究剩下的另一个问题,为何我们的方法返回的是一个列表,输出到客户端的时候,变成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. Spring IOC(五)依赖注入

    Spring IOC(五)依赖注入 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.autowire 五种注入方式测试 ...

  2. ApplicationContext(三)BeanFactory 初始化

    ApplicationContext(三)BeanFactory 初始化 上节我们提到容器初始化的第一步首先进行了属性的检验,下面就要开始第二步:进行 beanFactory 的初始化工作了. App ...

  3. Spring 系列教程之默认标签的解析

    Spring 系列教程之默认标签的解析 之前提到过 Spring 中的标签包括默认标签和自定义标签两种,而两种标签的用法以及解析方式存在着很大的不同,本章节重点带领读者详细分析默认标签的解析过程. 默 ...

  4. SpringMVC(前端设计模式)简介

    一.提供一个入口,让所有的请求都进行 / ,然后再分配给对应的页面,这就是前端设计模式(front) @WebServlet("/") 不过滤 .jsp public class ...

  5. java运行报错:nested exception is java.lang.NoSuchFieldError: INSTANCE,但使用@Test测试是好的

    解决方法: 原因是,在tomcat里,同名不同版本的jar包,默认加载版本低的.我项目里有两个httpclient jar包.一个4.2.5  另一个是4.5.所以加载了4.2.5的,而我要用的是4. ...

  6. 2018.11.07 NOIP训练 lzy的游戏(01背包)

    传送门 考虑对于每次最后全部选完之后剩下的牌的集合都对应着一种构造方法. 一个更接地气的说法: 设消耗的牌数为ttt,如果使用的牌的lll值之和也为ttt,则对应着一种构造方式让这种情形成立. 于是做 ...

  7. 2018.11.05 NOIP模拟 列队(差分约束)

    传送门 直接建边跑差分约束就可以了. 代码

  8. hadoop sqoop的常用名命令

    1 列出所有的ambari数据库中所有的表 Sqoop list-tables -connect  jdbc:mysql://localhost:3306/ambari -username ambar ...

  9. python 基础_ 打印输出 循环分支2

    一.在python3中的打印输出 1.输出字符串是print("hello world!!!") #输出字符串的时候可以是单引号括起来,也可以是双引号括起来.区别在于 2.输出变量 ...

  10. Arria10中的IOPLL与fPLL

    最近在用Arria10.从480降到270的过程中,IOPLL出现问题,大概是说几个Bank的IOPLL已经被占用,没有空间再给别的IOPLL去适配. 因为在工程中,所用的PLL多达35个之多,其中明 ...