本文描述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. centos 7配置网络 更新yum源

    cd /etc/sysconfig/network-script/ 找到对应的ifcfg-entxxxx文件,然后添加网关,修改dhcp为static,静态ip,添加IPADDR ip地址.onboo ...

  2. vi编辑器使用

    显示行号 set nu 取消行号 set nonu 定位到某一行 gg 定位到首行 G 定位到最后一行 在VI编辑器中切换调用外部shell命令 :!ifconfig   在编辑过程中,看ip地址 插 ...

  3. ASP.NET MVC 5 使用autofac实现DI

    使用Nuget添加Autofac.MVC的引用 启动项设置 注册Controller 注册ModelBinder 注册相关的web abstraction 为View层启用属性注入 为Action F ...

  4. Python全栈开发【面向对象】

    Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...

  5. 使用winshark分析三次握手,四次挥手

    三次握手 ip 106.120.167.67捕获的数据 数据信息   分析: 从图中可以看出,前三条为三次握手过程,使用TCP协议. 结合图,第一条为建立连接请求,客户端向服务器发送SYN=1的报文, ...

  6. 如何封装JS ----》JS设计模式《------ 封装与信息隐藏

    1. 封装与 信息隐藏之间的关系 实质是同一个概念的两种表达,信息隐藏式目的,二封装是借以达到目的的技术方法.封装是对象内部的数据表现形式和实现细节,要想访问封装过额对象中的数据,只有使用自己定义的操 ...

  7. Java获取用户ip

    /** * 获取客户端ip地址(可以穿透代理) * * @param request * @return */ public static String getRemoteAddr(HttpServl ...

  8. 结合实例详细介绍encodeURI()、encodeURIComponent()、decodeURI()、decodeURIComponent()使用方法

    在介绍encodeURI().encodeURIComponent().decodeURI().decodeURIComponent()方法前我们需要了解Global对象的概念:   Global(全 ...

  9. 中国知网cnki(永久会员账号)

    中国知网cnki(永久会员账号)大男孩免费分享   网站简介: (中国知网http://www.cnki.net/)中国知网是国家知识基础设施(National Knowledge Infrastru ...

  10. (原创)ssm sql 例子(freemarker+jsp)

    ssm整合地址:http://www.cnblogs.com/xiaohuihui96/p/6104351.html 接下讲解一个插入语句的流程和顺带讲解freemarker+jsp视图的整合 初次接 ...