在上一篇文章《路由其实也可以很简单》,我们解决了路由问题,这篇文章,我们来研究剩下的另一个问题,为何我们的方法返回的是一个列表,输出到客户端的时候,变成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. python 字符串占位符的使用

    name2='我是{} 我的专业是 {}'.format('张三','计算机科学技术')print(name2)

  2. 【UI测试】--合理性

  3. SpringBoot中关于@Enable***的注解详解

    出处:http://blog.csdn.net/qq_26525215 @EnableAspectJAutoProxy @EnableAspectJAutoProxy注解 激活Aspect自动代理 & ...

  4. VB.NET中的DLL编写和调用的最简单示例

    DLL(动态链接库)是一个很有用的东西,在开发大项目的时候显得非常重要,因为多人合作开发时,可以给每个人分配一个任务,用DLL完成,最后组合起来,就不会出现互相冲突的问题.这里给出最简单的DLL编写与 ...

  5. python的数字图像处理学习(3)

    高级滤波: from skimage import data,color,data_dir import matplotlib.pyplot as plt from skimage.morpholog ...

  6. matlab柱面图

    f=@(x,y)log(y);  % ln(x)函数,平行于x轴ezsurf(f,[-pi*2,pi*2,0,20])

  7. CSS Sprites (CSS 精灵) 技术

    CSS Sprites在国内很多人叫css精灵,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问该页面时,载入的图片就不会像以前那样一幅一幅地慢 ...

  8. C++STL set

    set set是一种集合容器,所包含的元素是唯一的,集合中的元素按一定顺序排列,元素插入过程是按排序规则插入,所以不能插入指定位置 set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树,插入和删除 ...

  9. 第15章:MongoDB-聚合操作--聚合管道--$match

    ①$match 用于对文档集合进行筛选,里面可以使用所有常规的查询操作符. 通常会放置在管道最前面的位置,理由如下: 1:快速将不需要的文档过滤,减少后续操作的数据量 2:在投影和分组之前做筛选,查询 ...

  10. 安卓中的makefile文件打印调试信息

    在安卓源码的makefile中有很多变量的值不方便确定,那么可以通过调试makefile文件来确定这些变量的值. $(warning  " TARGET_BOARD_PLATFORM =  ...