Asp.Net Web API 2第十四课——Content Negotiation(内容协商)
前言
阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html
本文描述ASP.NET Web API如何实现内容协商。
HTTP规范(RFC 2616)将内容协商定义为“在有多个表现可用时,为一个给定的响应选择最佳表现的过程”。在HTTP中内容协商的主要机制是以下请求报头:
- Accept:响应可接收的媒体类型,如“application/json”、“application/xml”,或者自定义媒体类型,如“application/vnd.example+xml”。
- Accept-Charset:可接收的字符集,如“UTF-8”或“ISO 8859-1”。
- Accept-Encoding:可接收的内容编码,如“gzip”。
- Accept-Language:优先选用的自然语言,如“en-us”。
服务器也可以查看HTTP请求的其它选项。例如,如果该请求含有一个X-Requested-With报头,它指示这是一个AJAX请求,在没有Accept报头的情况下,服务器可能会默认使用JSON。
本文将考察Web API如何使用Accept和Accept-Charset报头。(目前,还没有对Accept-Encoding或Accept-Language的内建支持。)
Serialization——序列化
如果Web API控制器返回一个CLR类型的响应,(请求处理)管线会对返回值进行序列化,并将其写入HTTP响应体。
例如,考虑以下控制器动作:
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”。
控制器也可以返回一个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);
}
该选项让你能够对响应细节进行更多的控制。你可以设置状态码、添加HTTP报头等等。
对资源进行序列化的对象叫做媒体格式化器。媒体格式化器派生于MediaTypeFormatter类。Web API提供了XML和JSON的媒体格式化器,因而你可以创建自定义的格式化器,以支持其它媒体类型。更多关于编写自定义格式化器的信息 http://www.cnblogs.com/aehyok/p/3460164.html。
内容协商的工作机制
首先,管线会获取HttpConfiguration对象的IContentNegotiator服务。它也会得到HttpConfiguration.Formatters集合的媒体格式化器列表。
接着,管线会调用IContentNegotiatior.Negotiate,在其中传递:
- 要序列化的对象类型
- 媒体格式化器集合
- HTTP请求
Negotiate方法返回两个信息片段:
- 要使用的格式化器
- 用于响应的媒体类型
如果未找到格式化器,方法返回null,而客户端会接收到一个HTTP的406(不可接收的)错误。
以下代码展示了控制器如何才能够直接调用内容协商:
public HttpResponseMessage GetProduct(int id)
{
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(MIME类型)
)
};
}
上述代码等价于管线的自动完成。
默认的内容协定
DefaultContentNegotiator类提供了IContentNegotiator的默认实现。它使用了几个选择格式化器的条件。
首先,格式化器必须能够对类型进行序列化,这是通过MediaTypeFormatter.CanWriteType来检验的。
其次,内容协商器要考查每个格式化器,并评估此格式化器与HTTP请求的匹配好坏。为了评估匹配情况,内容协商器要对此格式化器考察两样东西:
- SupportedMediaTypes集合,它含有一个可支持的媒体类型的列表。内容协商器尝试根据请求的Accept报头对这个列表进行匹配。注意,Accept报头可以包括范围。例如,“text/plain”可匹配“text/*”或“*/*”
- MediaTypeMappings集合,它含有对象一个MediaTypeMapping的对象列表。MediaTypeMapping类提供了一种泛型方式,以匹配带有媒体类型的HTTP请求。例如,它可以将一个自定义的HTTP报头映射到一个特定的媒体类型。
如果有多个匹配,带有最高质量因子的匹配获胜。例如:
Accept: application/json, application/xml; q=0.9, */*; q=0.1
在这个例子中,application/json具有隐含的质量因子1.0,因此它优于application/xml。
如果未找到匹配,内容协商器会尝试匹配请求体的媒体类型(有请求体时)。例如,如果请求含有JSON数据,内容协商器会找到JSON格式化器。
如果仍无匹配,内容协商器便简单地捡取能够对类型进行序列化的第一个格式化器。
选择字符编码
在选择格式化器之后,内容协商器会选择最佳字符编码。通过考察格式化器的SupportedEncodings,并根据请求的报送对其进行匹配(如果有)。
Asp.Net Web API 2第十四课——Content Negotiation(内容协商)的更多相关文章
- Asp.Net Web API 2第十八课——Working with Entity Relations in OData
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html. 本文的示例代码的下载地址 ...
- Asp.Net Web API 2第十六课——Parameter Binding in ASP.NET Web API(参数绑定)
导航 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html. 本文主要来讲解以下内容: ...
- Asp.Net Web API 2第十五课——Model Validation(模型验证)
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文参考链接文章地址htt ...
- Asp.Net Web API 2第十二课——Media Formatters媒体格式化器
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本教程演示如何在ASP.N ...
- Asp.Net Web API 2(CRUD操作)第二课
Asp.Net Web API 2(CRUD操作)第二课 Asp.Net Web API 导航 Asp.Net Web API第一课:入门http://www.cnblogs.com/aehyok ...
- Asp.Net Web API 2第十课——使用OWIN自承载Web API
详情请查看http://aehyok.com/Blog/Detail/71.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...
- Asp.net Web Api开发(第四篇)Help Page配置和扩展
https://blog.csdn.net/sqqyq/article/details/52708613
- Asp.Net Web API 2
Asp.Net Web API 2第十八课——Working with Entity Relations in OData 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导 ...
- 使用 OWIN Self-Host ASP.NET Web API 2
Open Web Interface for .NET (OWIN)在Web服务器和Web应用程序之间建立一个抽象层.OWIN将网页应用程序从网页服务器分离出来,然后将应用程序托管于OWIN的程序而离 ...
随机推荐
- 【转】linux下skype的安装使用
http://hi.baidu.com/24_jason/item/f85725306c7dbcf5df2221ca Fedora 18/17, CentOS/RHEL/SL 6.3 安装 Skype ...
- hive中order by,sort by, distribute by, cluster by作用以及用法
1. order by Hive中的order by跟传统的sql语言中的order by作用是一样的,会对查询的结果做一次全局排序,所以说,只有hive的sql中制定了order by所有的 ...
- IOS-Appium 自动化测试——环境配置及模拟器、真机跑测试
在MAC环境下配置IOS的appium的自动化测试环境,主要包含三个部分: 一.环境配置 1.安装homebrew(homebrew可以提供MAC OS无法提供的很多套件) ruby -e " ...
- cmd.ExecuteReader(CommandBehavior.CloseConnection)
有些开发人员坚持认为,如果您设置 CommandBehavior.CloseConnection 选项,则 DataReader 及其相关联的连接会在 DataReader 完成数据读取时自动关闭.这 ...
- 用java操作XML文件(DOM解析方式)
XML 可扩展标记语言(Extensible Markup Language),是独立于软件和硬件的传输工具. XML的作用: (1)用作配置文件 (2)简化数据共享 (3)简化数据传输 XML DO ...
- PHP各种缓存
缓存类型PHP缓存包括PHP变异缓存和PHP数据缓存两种:PHP编译缓存: PHP数据缓存: 对数据库数据进行缓存 对PHP模板数据缓存 js数据缓存
- 在updatepanel使用colorbox无效
今天在给一个使用colorbox的页面加了一个updatepanel后,colorbox无效了,原因是以前的页面初始化colorbox是用 $(document).ready(function(){ ...
- ajaxSetup和普通的ajax方法.
我明明写了ajaxSetup()方法可是它有时候却不一定是会执行,因为比如我common.js里写的ajaxSetup()方法,然后index.js里写了ajax方法,可是有的时候ajaxSetup里 ...
- Entity Framework 6.0 源码解读笔记(一)
internal static TResult ExecuteSingle<TResult>(IEnumerable<TResult> query, Expression qu ...
- 自定义php安装(2)—mysql安装和php整合
1. 写一段php 代码来测试是否成功! //目前你看不懂,没关系 <?php $conn=mysql_connect("localhost","root ...