一、内容协商的概念

HTTP规范将内容协商定义为“当有多个格式可用时为给定响应选择最佳格式的过程”。HTTP中内容协商的主要机制是这些请求标头:

Accept:响应可接受哪些媒体类型,例如“application / json”
Accept-Charset:可接受哪些字符集,例如UTF-8或ISO -。
Accept-Encoding:可接受哪些内容编码,例如gzip。
Accept-Language:首选的自然语言,例如“en-us”。

二、WebApi中序列化

如果Web API控制器将资源作为CLR类型返回,在管道将会将CLR类型序列化然后将其写入HTTP响应正文。

2.1  直接返回一个CLR对象

public Product GetProduct(int id)
{
var item = _products.FirstOrDefault(p => p.ID == id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}

客户端可能会发送此HTTP请求:

GET http://localhost.:21069/api/products/1 HTTP/1.1
Host: localhost.:
Accept: application/json, text/javascript, */*; q=0.01

作为响应,服务器可能会发送:

HTTP/1.1  OK
Content-Type: application/json; charset=utf-
Content-Length:
Connection: Close
{"Id":,"Name":"Gizmo","Category":"Widgets","Price":1.99}

  在这个栗子中,客户端请求JSON,Javascript或“任何”(* / *)。服务器使用Product对象的JSON表示进行响应。请注意,响应中的Content-Type标头设置为“application / json”。

2.2  控制器返回HttpResponseMessage对象

控制器还可以返回HttpResponseMessage对象,响应正文指定CLR对象时调用 CreateResponse 扩展方法:

public HttpResponseMessage GetProduct(int id)
{
  var item = _products.FirstOrDefault(p => p.ID == id);
  if (item == null)
  {
  throw new HttpResponseException(HttpStatusCode.NotFound);
  }
  return Request.CreateResponse(HttpStatusCode.OK, product,"application/json");
}

返回HttpResponseMessage时,我们可以更好地控制响应的详细信息。我们可以设置状态代码,添加HTTP标头,指定媒体格式等。

三、内容协商的工作原理

内容协商的工作过程可以分为三步:

第一步: 管道从HttpConfiguration对象获取IContentNegotiator服务 。

第二步: 从HttpConfiguration.Formatters集合中获取媒体格式化器列表 。

第三步: 管道调用IContentNegotiatior.Negotiate(type,request,famatters) 
  参数是:要序列化的对象类型,Request对象,媒体格式化器的集合
  返回结果:选用的格式化器,相应的媒体类型

这一步的过程是:Web API检测Request中Accept,Accept中有多种类型,从左到右,品质因子从高到低(默认q=1.0)并且同时尝试通过从格式化器列表中去找到一个匹配并且支持的媒体类。

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

很多情况下Request的Accept如上所示,如果Xml Formmatter存在,application/xml与Xml Formatter匹配上了,所以会以XML格式进行输出并返回。如果未找到格式化器,则Negotiate方法返回null,并且客户端接收HTTP错误406(不可接受)。

控制器如何直接调用内容协商的栗子:

public HttpResponseMessage GetProduct(int id)
{
var product = new Product()
{ Id = id, Name = "Gizmo", Category = "Widgets", Price = 1.99M };   //获取IContentNegotiator的服务实例
IContentNegotiator negotiator = this.Configuration.Services.GetContentNegotiator();   //Negotiate返会媒体类型和选择的formatter
ContentNegotiationResult result = negotiator.Negotiate(typeof(Product), this.Request, this.Configuration.Formatters);
if (result == null)
{
var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
throw new HttpResponseException(response));
   } return new HttpResponseMessage()
  {
    Content = new ObjectContent<Product>(
   product, // 序列化的对象
   result.Formatter, // 采用的formmter
   result.MediaType.MediaType // 媒体类型
    )
  };
}

如果想了解更多内容协商的内容,可以查看官网

Web API中的内容协商的更多相关文章

  1. 【ASP.NET Web API教程】4.3 ASP.NET Web API中的异常处理

    原文:[ASP.NET Web API教程]4.3 ASP.NET Web API中的异常处理 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...

  2. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

  3. ASP.NET Web API中的Controller

    虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...

  4. Web APi 2.0优点和特点?在Web APi中如何启动Session状态?

    前言 曾几何时,微软基于Web服务技术给出最流行的基于XML且以扩展名为.asmx结尾的Web Service,此服务在.NET Framework中风靡一时同时也被.NET业界同仁所青睐,几年后在此 ...

  5. 在ASP.NET Web API中使用OData

    http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...

  6. Web Api中的get传值和post传值

    GET 方式 get方式传参 我们一般用于获取数据做条件筛选,也就是 “查” 1.无参 var look = function () { $.ajax({ type: "GET", ...

  7. WEB API 中HTTP的get、post、put,delete 请求方式

    一.WEB API 中HTTP 请求方式的四个主要方法 (GET, PUT, POST, DELETE), 按照下列方式映射为 CURD 操作: 1.POST 用于新建资源,服务端在指定的URI 上创 ...

  8. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【五】——在Web Api中实现Http方法(Put,Post,Delete)

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在Web Api中,我们对资源的CRUD操作都是通过相应的Http方法来实现——Post(新 ...

  9. ASP.NET Web API 中的异常处理(转载)

    转载地址:ASP.NET Web API 中的异常处理

随机推荐

  1. 洛谷P1063能量项链题解

    $题目$ 不得不说,最近我特别爱刷这种区间DP题,因为这个跟其他的DP有些不一样的地方,主要是有一定的套路,就是通过小区间的状态更新大区间,从而得到原题给定区间的最优解. $但是$ 这个题应该跟$石子 ...

  2. Codeforces715 B. Complete The Graph

    传送门:>Here< 题意:给出一张带权无向图,其中有一些边权为0.要求将边权为0的边的边权重置为一个任意的正整数,使得从S到T的最短路为L.判断是否存在这种方案,如果存在输出任意一种 解 ...

  3. 树莓派(Raspberry Pi)使用Shell编写的极简Service

    树莓派(Raspberry Pi)运行的系统是基于Debian的,不仅可以运行Shell,还支持systemd和docker,可以编写一个简单的服务,让其在启动时运行,执行一些自动化的操作.这里在Ra ...

  4. Spring学习记录

    Java类定义配置@Configuration //标记为配置类@ComponentScan //标记为扫描当前包及子包所有标记为@Component的类@ComponentScan(basePack ...

  5. android TextView字体设置最少占多少行. 及其 Java String 字符串操作 . .

    ①  字体设置: 修改代码 :  GridViewActivity.java priceTv为 TextView priceTv.setMaxLines(3); //当多与7个字fu的时候 , 其余字 ...

  6. 【BZOJ5302】[HAOI2018]奇怪的背包(动态规划,容斥原理)

    [BZOJ5302][HAOI2018]奇怪的背包(动态规划,容斥原理) 题面 BZOJ 洛谷 题解 为啥泥萌做法和我都不一样啊 一个重量为\(V_i\)的物品,可以放出所有\(gcd(V_i,P)\ ...

  7. HGOI 20190310 题解

    /* 又是又双叒叕WA的一天... 我太弱鸡了... 今天上午打了4道CF */ Problem 1 meaning 给出q组询问,求下列函数的值$ f(a) = \max\limits_{0 < ...

  8. css border制作小三角形状及气泡框(兼容IE6)

    先看下CSS盒模型 一个盒子包括: margin+border+padding+content 上下左右边框交界处出呈现平滑的斜线. 利用这个特点, 通过设置不同的上下左右边框宽度或者颜色可以得到小三 ...

  9. Palindrome Function HDU - 6156(数位dp)

    要求m-n内在l-r进制下的是回文数的总个数. dp[进制][从第j为开始][目前到达第k位] = 总的方案数 dfs枚举目前的到达的位置,这个数开始的位置,进制,前导零,限制条件,然后枚举的时候如果 ...

  10. Codeforces Round #516 (Div. 2)D. Labyrinth(BFS)

    题目链接:http://codeforces.com/contest/1064/problem/D 题目大意:给你一个n*m的图,图中包含两种符号,'.'表示可以行走,'*'表示障碍物不能行走,规定最 ...