一、内容协商的概念

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. Hard Life UVA - 1389(最大密度子图 输出点集)

    题意: rt 解析: 我用的第二种方法... s向所有的边连权值为1的边 所有的点向t连权值为mid的边 如果存在u -  > v  则边向u和v分别连一条权值为INF的边 二分mid 用dfs ...

  2. PHP 事务写法

    $md=new Model(); //创建事务 $md->startTrans(); //开始事务 $md->table("ym_xxx")->where(&qu ...

  3. 【agc030f】Permutation and Minimum(动态规划)

    [agc030f]Permutation and Minimum(动态规划) 题面 atcoder 给定一个长度为\(2n\)的残缺的排列\(A\),定义\(b_i=min\{A_{2i-1},A_{ ...

  4. 【BZOJ5213】[ZJOI2018]迷宫(神仙题)

    [BZOJ5213][ZJOI2018]迷宫(神仙题) 题面 BZOJ 洛谷 题解 首先可以很容易的得到一个\(K\)个点的答案. 构建\(K\)个点分别表示\(mod\ K\)的余数.那么点\(i\ ...

  5. 子网站不继承父的WEBCONFIG

    环境 W10 IIS10  / WIN2012 IIS上以前有一个网站,后来写了一个接口项目,需要当成WEB应用程序挂到这网站下. 在右击添加应用程序,指向接口项目后.发现访问不了接口项目.死活配置有 ...

  6. cf1088D Ehab and another another xor problem (构造)

    题意:有两数a,b,每次你可以给定c,d询问a xor c和b xor d的大小关系,最多询问62次($a,b<=2^{30}$),问a和b 考虑从高位往低位做,正在做第i位,已经知道了a和b的 ...

  7. 英语考试 FZU - 2254 (最小生成树)

    先选一个单词出来完全自己背,然后从这个单词到其他各个单词所需要的精力看成距离,然后用最小生成树把这些单词连接起来,就是通过我现在选的这个单词到其他各个单词的最小精力,然后再加上把这个单词背起来的精力, ...

  8. Building Microservices with Spring Boot and Apache Thrift. Part 2. Swifty services

    http://bsideup.blogspot.com/2015/04/spring-boot-thrift-part2.html     In previous article I showed y ...

  9. 洛谷P4307 球队收益

    题意:有n个球队,m场比赛. 每个球队都已经有些胜负场次了. 每个球队的收益为Ci * wini2 - Di * losei2. 求最小可能总收益. 解: 先看出一个模型:用一流量代表一个胜场,每场比 ...

  10. pyinstall实现不显示控制窗口

    做图形界面的时候,总会弹出一个cmd的黑框框,为了美观,通常希望将其隐藏. 查找资料得知:1.pythonw.exe .py不会出现(此方法没试过) 2.python.exe .pyw即将py文件的后 ...