一、内容协商的概念

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. [踩过的坑]Elasticsearch.Net 官网示例的坑

    经过昨天的ElasticSearch 安装,服务以及可以启动了,接下来就可以开发了,找到了官网提供的API以及示例,Es 官方提供的.net 客户端有两个版本一个低级版本: [Elasticsearc ...

  2. Snowflake Snow Snowflakes POJ - 3349 Hash

    题意:一个雪花有六个角  给出N个雪花 判断有没有相同的(可以随意旋转) 参考:https://blog.csdn.net/alongela/article/details/8245005 注意:参考 ...

  3. UOJ274 [清华集训2016] 温暖会指引我们前行 【LCT】【最大生成树】

    题目分析: 差评,最大生成树裸题.hack数据还卡常. 代码: #include<bits/stdc++.h> using namespace std; ; struct LCT{ ],d ...

  4. 【XSY2729】欧拉子图 无向图连通性 数学

    题目大意 给你一个\(n\)个点\(m\)条边的无向图(可能有重边),对于这个图的边集的子集(一共有\(2^m\)个),如果其导出的子图的每个联通块内都存在欧拉回路,我们就把答案加上这个子图的边数的平 ...

  5. Codeforces Round #471 (Div. 2) F. Heaps(dp)

    题意 给定一棵以 \(1\) 号点为根的树.若满足以下条件,则认为节点 \(p\) 处有一个 \(k\) 叉高度为 \(m\) 的堆: 若 \(m = 1\) ,则 \(p\) 本身就是一个 \(k\ ...

  6. 【UOJ#246】套路(动态规划)

    [UOJ#246]套路(动态规划) 题面 UOJ 题解 假如答案的选择的区间长度很小,我们可以做一个暴力\(dp\)计算\(s(l,r)\),即\(s(l,r)=min(s(l+1,r),s(l,r- ...

  7. [luogu2571][bzoj1857][SCOI2010]传送门【三分套三分】

    题目描述 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段.两条传送带分别为线段AB和线段CD.lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R.现在lxh ...

  8. [CF976E]Well played!

    题目描述 Recently Max has got himself into popular CCG "BrainStone". As "BrainStone" ...

  9. __init__、__new__、__call__ 方法

    __init__方法 __init__方法负责对象的初始化,系统执行该方法前,其实该对象已经存在了,要不然初始化什么东西呢?先看例子: # class A(object): python2 必须显示地 ...

  10. [HNOI2015]落忆枫音 解题报告

    [HNOI2015]落忆枫音 设每个点入度是\(d_i\),如果不加边,答案是 \[ \prod_{i=2}^nd_i \] 意思是我们给每个点选一个父亲 然后我们加了一条边,最后如果还这么统计,那么 ...