本文描述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. Android ActionBar 初探

    1.指南,例子,个人感觉 首先上官网指南链接http://developer.android.com/guide/topics/ui/actionbar.html 参考了官网上的例子http://de ...

  2. Jquery制作--焦点图淡出淡入

    之前写了一个焦点图左右轮播的,感觉淡出淡入用得也比较多,就干脆一起放上来啦.这个容器用了百分比宽度,图片始终保持居中处理,定宽或者自适应宽度都是可以的. 兼容到IE6+以上浏览器,有淡出淡入速度和切换 ...

  3. Gcc的Makefile简单使用

    Gcc的Makefile简单使用http://blog.chinaunix.net/uid-9330295-id-2425867.html

  4. .htaccess中Apache配置详解

    1.<IfDefine> 指令 说明 封装一组只有在启动时当测试结果为真时才生效的指令 语法 <IfDefine [!]parameter-name> ... </IfD ...

  5. Android 自动安装脚本

    建立一个install.bat,写入下面 adb install -r %1PAUSE 把apk拖拽到install.bat上

  6. 419. Battleships in a Board

    https://leetcode.com/problems/battleships-in-a-board/ 给定一个N×N的棋盘,有任意数量的1×N或N×1大小的"船",注意船船之 ...

  7. ABAP 特性值取数 非BAPI方式

    特性值在ausp,objnr  一般是客户号或是客户号拼接的,客户号加特征字段特征类别就可以取了

  8. Python: 处理mongodb文档,怎么让UTC时间转换为本地时间?

    存储数据到MongoDB数据库时,一般我们会加一个更新数据的时间update_time.这时在python代码中 会用到datetime模块以便获取当前系统时间,但是存入到MongoDB数据库时,存储 ...

  9. 初识MVC

    本人是一个程序员,我也是一个很普通很普通的人,当我初学一些东西的时候感觉都很难,毕竟没有天才的头脑,没有高等的学历,但是我有的只是努力,只是拼搏的精神,人都是为自己而活,也可能为他人而活,但是有时候在 ...

  10. SpringMVC后台接收list类型的数据的实现方式

    一.背景 最近在做一些东西的时候,遇到一个需要Springmvc后台接收list类型数据的需求,几经辗转才完美解决了这个问题,今天记下来方便以后使用,也分享给需要的小伙伴们~ 二.实现方式 1.实现方 ...