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的程序而离 ...
随机推荐
- MC的缓存雪崩现象和缓存无底洞的原因以及导致的后果的总结
缓存雪崩一般是由某个缓存节点失效,导致其他节点的缓存命中率下降,缓存中确实的数据去数据库查询,短时间内,造成数据库服务器的崩溃. 这时,我们需要重启数据库,但重启一段时间后,又会被压垮,但此时缓存的数 ...
- HTTP的应用httpclient 和线程
package com.example.service; import java.io.IOException; import java.io.InputStream; import org.apac ...
- SQL 2012 alwayson设置只读路由
ALTER AVAILABILITY GROUP [sqlmaxiangqianbd] MODIFY REPLICA ON N'maxiangqian1' WITH (SECONDARY_R ...
- {Links}{Matting}{Saliency Detection}{Superpixel}Source links
自然图像抠图/视频抠像技术发展情况梳理(image matting, alpha matting, video matting)--计算机视觉专题1 http://blog.csdn.net/ansh ...
- linux C学习笔记02--共享内存(进程同步)
system V下3中进程同步:共享内存(shared memory),信号量(semaphore)和消息队列(message queue) 调试了下午,终于调通啦! 运行./c.out 输出共享内存 ...
- SQL Server 存储过程自定义生成ID号
* FROM sys.tables WHERE name=N'EmployeeNo_Identity') DROP TABLE EmployeeNo_Identity GO CREATE TABLE ...
- 【html/css】html/css命名规范
无论做什么,规则总是最重要的.无规矩不成方圆,有了规矩,我们才能有规可循,有则可依,人与人之间才能正常的交流交往. 人人都有自己的命名习惯,不过,代码是需要交流的,当有些命名习惯仅只自己能看懂,甚至自 ...
- AngularJs自定义指令详解(2) - template
一些用于定义行为的指令,可能不需要使用template参数. 当指定template参数时,其值可以是一个字符串,表示一段HTML文本,也可以是一个函数,这函数接受两个参数:tElement和tAtt ...
- 使用 IntraWeb (42) - 测试读取 SqLite (一)
为通过 FireDAC(XE5开始支持的) 使用 SqLite, 现在已换成 XE6 + IntraWeb v14.0.32 Ultimate. 首先把官方提供的 C:\Users\Public\Do ...
- 搭载hexo+github博客系统
一.安装 Node.js 在官网 http://nodejs.org/ 下载winwos版本,点击安装完成即可. 二.git环境安装 对于git的安装,网上已经大量资料,就不赘述了. 三.安装 hex ...