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

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

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

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

  3. servlet 高级知识之Filter

    Filter叫做拦截器, 对目标资源拦截,拦截HTTP请求和HTTP响应,本质是对url进行拦截. 与serlvet不同的是, Filter的初始化是随着服务器启动而启动. 在Filter接口中定义了 ...

  4. C语言基础第四次作业

    题目7-2,九九乘法表 1.实验代码: #include<stdio.h> int main() { int N, i, j, q; scanf("%d",&N ...

  5. 9月list

    开学了,我已经是大三的老学姐了,难受! 哇,时间过得好快啊,感觉自己快毕业了,肿么办!!! 9月了,快一年了,其实很多东西都变了,比如你. 9月4日的list:

  6. 18 包 ,logging模块使用

    包: 1 什么是包: 包就是一个包含有__init__.py文件的文件夹 宝本质就是一种模块,即包就是用包导入使用的,包内部包含的文件也都是用来被导入使用 2 为什么要用包 包就是文件夹,那文件加就是 ...

  7. GOAP

    市面上Unity人工智能的书籍基本上都是介绍这几个方面: AI角色的自主移动 --- 操控行为, 单体,小队,群体的行为. 我之前的文章 Unity Movement AI (一) , Unity M ...

  8. GUI的优化操作/添加背景图片等

    一.背景图片的添加这是JAVA中添加背景图片的方式,基本思路先建立一个Label标签,然后建立一个层次的布局,将label标签添加到最下面去. ImageIcon image=new ImageIco ...

  9. 爬虫模块之selenium模块

    一 模块的介绍 selenium模块最开始是一个自动化测试的工具,驱动浏览器完全模拟浏览器自动测试. from selenium import webdriver # 驱动浏览器 browser=we ...

  10. mysql之索引查询2

    一 索引的创建 索引减慢了 写的操作,优化了读取的时间 index:普通索引,加速了查找的时间. fulltext:全文索引,可以选用占用空间非常大的文本信息的字段作为索引的字段.使用fulltext ...