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.: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}

在这个例子中,客户端请求(指定)了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,并根据请求的报送对其进行匹配(如果有)。

 
 

Content Negotiation(内容协商)的更多相关文章

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

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

  2. Content Negotiation in ASP.NET Web API

    本文描述Web API实现内容协商(content negotiation). The HTTP specification (RFC 2616) defines content negotiatio ...

  3. Spring MVC Content Negotiation 转载

    Spring MVC Content Negotiation 2017年11月15日 00:21:21 carl-zhao 阅读数:2983   Spring MVC有两种方式生成output的方法: ...

  4. WebApi2官网学习记录---Content Negotiation

    Content Negotiation的意思是:当有多种Content-Type可供选择时,选择最合适的一种进行序列化并返回给client. 主要依据请求中的Accept.Accept-Charset ...

  5. Content Negotiation using Spring MVC

    There are two ways to generate output using Spring MVC: You can use the RESTful @ResponseBody approa ...

  6. 使用ASP.NET Core 3.x 构建 RESTful API - 3.4 内容协商

    现在,当谈论起 RESTful Web API 的时候,人们总会想到 JSON.但是实际上,JSON 和 RESTful API 没有半毛钱关系,只不过 JSON 恰好是RESTful API 结果的 ...

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

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

  8. W3C词汇和术语表

    以A字母开头的词汇 英文 中文 abstract module 抽象模组 access 访问.存取 access control 存取控制 access control information 存取控 ...

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

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

随机推荐

  1. java 中间String分类

    String a = "aaa"; 用这样的方式的时候java首先在内存中寻找"aaa"字符串.假设有.就把aaa的地址给它 假设没有则创建 String a ...

  2. ASP.NET MVC Boilerplate简介

    ASP.NET MVC Boilerplate简介 ASP.NET MVC Boilerplate是专业的ASP.NET MVC模版用来创建安全.快速.强壮和适应性强的Web应用或站点.它在微软默认M ...

  3. 让UIAlertController兼容的同时iphone和ipad

    让UIAlertController兼容的同时iphone和ipad by 吴雪莹 var alert = UIAlertController(title: nil, message: message ...

  4. KafkaOffsetMonitor

    Kafka实战-KafkaOffsetMonitor   1.概述 前面给大家介绍了Kafka的背景以及一些应用场景,并附带上演示了Kafka的简单示例.然后,在开发的过程当中,我们会发现一些问题,那 ...

  5. PeopleRank从社交网络中发现个体价值

    阅读导读: 1.什么是PeopleRank? 2.PeopleRank和PageRank有什么差别? 3.PR分析微博数据时,怎样对微博单个账号评分? 4.R语言怎样递归计算矩阵特征值? 5.怎样计算 ...

  6. oracle_解锁表_解锁用户

    1.解锁用户 以dba身份登录   sqlplus / as sysdba alter user scott account unlock; 2.解锁表 alter   system   kill   ...

  7. BZOJ 1355 Baltic2009 Radio Transmission KMP算法

    标题效果:给定一个字符串,求最小周期节(不能整除) 示例Hint这是错误的忽略了就好了 环路部分应该是cab 这个称号充分利用KMP在next自然阵列,那是,n-next[n]它表示一个循环节 POJ ...

  8. CSharp设计模式读书笔记(14):职责链模式(学习难度:★★★☆☆,使用频率:★★☆☆☆)

    职责链模式(Chain of Responsibility  Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象 ...

  9. Samza/KafkaAnalysizing

    Apache Samza is a distributed stream processing framework. It uses Apache Kafka for messaging, and A ...

  10. SOA、REST 和六边形架构

    SOA.REST 和六边形架构 上一篇:<IDDD 实现领域驱动设计-架构之经典分层> 阅读目录: SOA-面向服务架构 REST 与 RESTful 资源(Resources) 状态(S ...