本文描述Web API实现内容协商(content negotiation)。

The HTTP specification (RFC 2616) defines content negotiation as “the process of selecting the best representation for a given response when there are multiple representations available.”

HTTP中内容协商机制是由以下请求头实现的:

  • Accept: 响应支持的媒体类型, 比如 “application/json,” “application/xml,” 或者自定义的媒体类型如 "application/vnd.example+xml"
  • Accept-Charset: 接受哪种字符集,例如 UTF-8 或 ISO 8859-1.
  • Accept-Encoding: 接受哪种内容编码,例如 gzip.
  • Accept-Language: 优先支持的自然语言,例如 “en-us”.

如果没有Accept头部,服务器也可以通过查看其它部分来决定。例如,如果头部包含X-Requested-With,表明是一个AJAX请求,那么服务器默认选择JSON格式。

本文中,我们将看到Web API使用Accept和Accept-Charset头部.(目前为止,没有内置的实现支持Accept-Encoding或者Accept-Language)

1. 序列化

如果Web API返回一个CLR类型,那么闲序列化,然后写到HTTP的响应体。

如果客户端的请求为:

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

那么,很可能就返回

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

序列化资源的对象称为媒体格式化器(media formatter)。查看MediaTypeFormatter类,Web API默认支持XML和JSON,也可以自定义。

2. 内容协商怎么工作?

首先,Web API管道从HttpConfiguration对象获取IContentNegotiator服务,IContentNegotiator服务从HttpConfiguration.Formatters集合获取到_媒体格式化器_,

接着,管道调用IContentNegotiatior.Negotiate,传递:

  • 要序列化的类型

  • 媒体格式化器列表

  • HTTP 请求

Negotiate方法返回两部分信息:

  • 使用哪个媒体格式化器(media formatter)

  • 返回什么媒体类型(media type)

如果找不到格式器,Negotiate方法返回null,客户端收到一个406(Not Acceptable)错误。

解释内容协商的演示代码:

public HttpResponseMessage GetProduct(int id, bool contentNegotiate)
{
var product = new Product()
{ Id = id, Name = "Gizmo", Category = "Widgets", Price = 1.99M }; IContentNegotiator negotiator = this.Configuration.Services.GetContentNegotiator(); 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, // What we are serializing
result.Formatter, // The media formatter
result.MediaType.MediaType // The MIME type
)
};
}

管道就如上述代码一样自动处理的。

默认的内容协商

DefaultContentNegotiator是IContentNegotiator的默认实现。

首先,媒体格式化器(formatter)要能够序列化当前类型,CanWriteType方法来验证的。

接着,内容协商器查看每一个媒体格式化器,并计算和HTTP请求的匹配度。

  • SupportedMediaTypes集合。内容协商器匹配每一个Accept头部

  • MediaTypeMappings集合。

如果有多个匹配,选择质量因子最高的一个。

Accept: application/json, application/xml; q=0.9, */*; q=0.1

如上,application/json将是最优的。

如果没有任何的匹配,那么内容协商器将匹配请求体,如果请求体是JSON数据,那么内容协商器将寻找一个JSON序列化器。

如果仍没有匹配,那么内容协商器将简单地选择第一个能够序列化当前类型的序列化器。

3. 字符编码选择

序列化器选定之后,通过序列化器上的SupportedEncodings属性来选择最好的内容编码,并且与Accept-Charset头部能够匹配。

Content Negotiation in ASP.NET Web API的更多相关文章

  1. 【ASP.NET Web API教程】6 格式化与模型绑定

    原文:[ASP.NET Web API教程]6 格式化与模型绑定 6 Formats and Model Binding 6 格式化与模型绑定 本文引自:http://www.asp.net/web- ...

  2. Asp.Net Web API 2第十四课——Content Negotiation(内容协商)

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...

  3. ASP.NET Web API - ASP.NET MVC 4 系列

           Web API 项目是 Windows 通信接口(Windows Communication Foundation,WCF)团队及其用户激情下的产物,他们想与 HTTP 深度整合.WCF ...

  4. ASP.NET Web API系列教程目录

    ASP.NET Web API系列教程目录 Introduction:What's This New Web API?引子:新的Web API是什么? Chapter 1: Getting Start ...

  5. 【ASP.NET Web API教程】6.3 内容协商

    本文是Web API系列教程的第6.3小节 6.3 Content Negotiation 6.3 内容协商 摘自:http://www.asp.net/web-api/overview/format ...

  6. 让ASP.NET Web API支持text/plain内容协商

    ASP.NET Web API的内容协商(Content Negotiation)机制的理想情况是这样的:客户端在请求头的Accept字段中指定什么样的MIME类型,Web API服务端就返回对应的M ...

  7. 【转】WCF和ASP.NET Web API在应用上的选择

    文章出处:http://www.cnblogs.com/shanyou/archive/2012/09/26/2704814.html 在最近发布的Visual Studio 2012及.NET 4. ...

  8. ASP.NET Web API——选择Web API还是WCF

    WCF是.NET平台服务开发的一站式框架,那么为什么还要有ASP.NET Web API呢?简单来说,ASP.NET Web API的设计和构建只考虑了一件事情,那就是HTTP,而WCF的设计主要是考 ...

  9. asp.net web api的自托管模式HttpSelfHostServer可以以控制台程序或windows服务程序为宿主,不单单依赖于IIS web服务器

    Self-Hosting ASP.NET Web API http://theshravan.net/self-hosting-asp-net-web-api/ http://www.piotrwal ...

随机推荐

  1. C#语言之“中英文混合字符串对齐”的方法

    参考自:(1)http://www.cnblogs.com/cnluoke/articles/1213398.html (2)http://www.cnblogs.com/sql4me/archive ...

  2. GetWord 3.3 屏幕取词

    1. 缘起 要搞一个作弊软件,需要把屏幕上的试题取下来. 据说针对IE的取词很难,所以也就打消了自己开发的念头,找一找好用的控件. 发现了两个可以用的,一个是金山词霸的XdictGrb.dll文件,一 ...

  3. Servlet和CGI的区别

    Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销 ...

  4. android App使用新浪微博sdk的使用总结

    问题1:注册app的key 问题2:在微博开放平台,我的应用中心中,设置应用的基本信息的时候其中有一项,是设置你的应用的签名,签名是需要在安卓设备上安装一个生成签名的app(这个app界面很丑,这点我 ...

  5. Django模型的Field Types总结

    转:http://blog.csdn.net/devil_2009/article/details/41735611 Field Types 常用参数: null 如果设置为 True , Djang ...

  6. getPx function

    function getPX(str){  return str.substring(0,str.indexOf('px'));}

  7. Java读取word文件,字体,颜色

    在Android读取Word文件时,在网上查看时可以用tm-extractors,但好像没有提到怎么读取Word文档中字体的颜色,字体,上下标等相关的属性.但由于需要,要把doc文档中的内容(字体,下 ...

  8. 文件权限:普通(r、w、x)和特殊(s、t)

     linux中,常常涉及到权限的问题.文件的权限有3组,owner,group,other,每一组都有rwx三种设置.r(4):可读:w(2):可写:x(1):可执行.我们在执行shell命令ls - ...

  9. java.lang.NullPointerException的可能原因及处理

    java.lang.NullPointerException的可能原因及处理 java.lang.NullPointerException具体意思是空指针异常,最常见的问题就是没有初始化. 字符串等数 ...

  10. POJ2777

    http://poj.org/problem?id=2777 前几天看到一个大神说,要搞,就搞专题或者套题,我觉得现在这么菜的我,还是搞搞专题吧. 一道比较裸也比较基础的线段树的题目. 题意:就是有一 ...