天天看點

【ASP.NET Web API教程】6.3 内容協商6.3 Content Negotiation 6.3 内容協商

摘自:http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation

By Mike Wasson|May 20, 2012

作者:Mike Wasson | 日期:2012-3-20

This article describes how ASP.NET Web API implements content negotiation.

本文描述ASP.NET Web API如何實作内容協商。

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.” The primary mechanism for content negotiation in HTTP are these request headers:

HTTP規範(RFC 2616)将内容協商定義為“在有多個表現可用時,為一個給定的響應選擇最佳表現的過程”。在HTTP中内容協商的主要機制是以下請求報頭:

Accept: Which media types are acceptable for the response, such as “application/json,” “application/xml,” or a custom media type such as "application/vnd.example+xml"

Accept:響應可接收的媒體類型,如“application/json”、“application/xml”,或者自定義媒體類型,如“application/vnd.example+xml”。

Accept-Charset: Which character sets are acceptable, such as UTF-8 or ISO 8859-1.

Accept-Charset:可接收的字元集,如“UTF-8”或“ISO 8859-1”。

Accept-Encoding: Which content encodings are acceptable, such as gzip.

Accept-Encoding:可接收的内容編碼,如“gzip”。

Accept-Language: The preferred natural language, such as “en-us”.

Accept-Language:優先選用的自然語言,如“en-us”。

The server can also look at other portions of the HTTP request. For example, if the request contains an X-Requested-With header, indicating an AJAX request, the server might default to JSON if there is no Accept header.

伺服器也可以檢視HTTP請求的其它選項。例如,如果該請求含有一個X-Requested-With報頭,它訓示這是一個AJAX請求,在沒有Accept報頭的情況下,伺服器可能會預設使用JSON。

In this article, we’ll look at how Web API uses the Accept and Accept-Charset headers. (At this time, there is no built-in support for Accept-Encoding or Accept-Language.)

本文将考察Web API如何使用Accept和Accept-Charset報頭。(目前,還沒有對Accept-Encoding或Accept-Language的内建支援。)

If a Web API controller returns a resource as CLR type, the pipeline serializes the return value and writes it into the HTTP response body.

如果Web API控制器傳回一個CLR類型的響應,(請求處理)管線會對傳回值進行序列化,并将其寫入HTTP響應體。

For example, consider the following controller action:

例如,考慮以下控制器動作:

A client might send this HTTP request:

用戶端可能會發送這樣的HTTP請求:

In response, the server might send:

伺服器可能會發送以下響應:

In this example, the client requested either JSON, Javascript, or “anything” (*/*). The server responsed with a JSON representation of the Product object. Notice that the Content-Type header in the response is set to "application/json".

在這個例子中,用戶端請求(指定)了JSON、Javascript、或“任意格式(*/*)”。伺服器以一個Product對象的JSON表示作出了響應。注意,響應中的Content-Type報頭已被設定成“application/json”。

A controller can also return an HttpResponseMessage object. To specify a CLR object for the response body, call the CreateResponse extension method:

控制器也可以傳回一個HttpResponseMessage對象。為了指定響應體的CLR對象,要調用CreateResponse擴充方法(注意,以下代碼是控制器中的一個動作方法,不是整個控制器 — 譯者注):

This option gives you more control over the details of the response. You can set the status code, add HTTP headers, and so forth.

該選項讓你能夠對響應細節進行更多的控制。你可以設定狀态碼、添加HTTP報頭等等。

The object that serializes the resource is called a media formatter. Media formatters derive from the MediaTypeFormatter class. Web API provides media formatters for XML and JSON, and you can create custom formatters to support other media types. For information about writing a custom formatter, see Media Formatters.

對資源進行序列化的對象叫做媒體格式化器(media formatter)。媒體格式化器派生于MediaTypeFormatter類。Web API提供了XML和JSON的媒體格式化器,因而你可以建立自定義的格式化器,以支援其它媒體類型。更多關于編寫自定義格式化器的資訊,請參閱“媒體格式化器(本系列教程的第6.1小節 — 譯者注)”。

First, the pipeline gets the IContentNegotiator service from the HttpConfiguration object. It also gets the list of media formatters from the HttpConfiguration.Formatters collection.

首先,管線會擷取HttpConfiguration對象的IContentNegotiator服務。它也會得到HttpConfiguration.Formatters集合的媒體格式化器清單。

Next, the pipeline calls IContentNegotiatior.Negotiate, passing in:

接着,管線會調用IContentNegotiatior.Negotiate,在其中傳遞:

The type of object to serialize

要序列化的對象類型

The collection of media formatters

媒體格式化器集合

The HTTP request

HTTP請求

The Negotiate method returns two pieces of information:

Negotiate方法傳回兩個資訊片段:

Which formatter to use

要使用的格式化器

The media type for the response

用于響應的媒體類型

If no formatter is found, the Negotiate method returns null, and the client recevies HTTP error 406 (Not Acceptable).

如果未找到格式化器,方法傳回null,而用戶端會接收到一個HTTP的406(不可接收的)錯誤。

The following code shows how a controller can directly invoke content negotiation:

以下代碼展示了控制器如何才能夠直接調用内容協商:

This code is equivalent to the what the pipeline does automatically.

上述代碼等價于管線的自動完成

The DefaultContentNegotiator class provides the default implementation of IContentNegotiator. It uses several criteria to select a formatter.

DefaultContentNegotiator類提供了IContentNegotiator的預設實作。它使用了幾個選擇格式化器的條件。

First, the formatter must be able to serialize the type. This is verified by calling MediaTypeFormatter.CanWriteType.

首先,格式化器必須能夠對類型進行序列化,這是通過MediaTypeFormatter.CanWriteType來檢驗的。

Next, the content negotiator looks at each formatter and evaluates how well it matches the HTTP request. To evaluate the match, the content negotiator looks at two things on the formatter:

其次,内容協商器要考查每個格式化器,并評估此格式化器與HTTP請求的比對好壞。為了評估比對情況,内容協商器要對此格式化器考察兩樣東西:

The SupportedMediaTypes collection, which contains a list of supported media types. The content negotiator tries to match this list against the request Accept header. Note that the Accept header can include ranges. For example, “text/plain” is a match for text/* or */*.

SupportedMediaTypes集合,它含有一個可支援的媒體類型的清單。内容協商器嘗試根據請求的Accept報頭對這個清單進行比對。注意,Accept報頭可以包括範圍。例如,“text/plain”可比對“text/*”或“*/*”

The MediaTypeMappings collection, which contains a list of MediaTypeMapping objects. The MediaTypeMapping class provides a generic way to match HTTP requests with media types. For example, it could map a custom HTTP header to a particular media type.

MediaTypeMappings集合,它含有對象一個MediaTypeMapping的對象清單。MediaTypeMapping類提供了一種泛型方式,以比對帶有媒體類型的HTTP請求。例如,它可以将一個自定義的HTTP報頭映射到一個特定的媒體類型。

If there are multiple matches, the match with the highest quality factor wins. For example:

如果有多個比對,帶有最高品質因子的比對獲勝。例如:

In this example, application/json has an implied quality factor of 1.0, so it is preferred over application/xml.

在這個例子中,application/json具有隐含的品質因子1.0,是以它優于application/xml。

If no matches are found, the content negotiator tries to match on the media type of the request body, if any. For example, if the request contains JSON data, the content negotiator looks for a JSON formatter.

如果未找到比對,内容協商器會嘗試比對請求體的媒體類型(有請求體時)。例如,如果請求含有JSON資料,内容協商器會找到JSON格式化器。

If there are still no matches, the content negotiator simply picks the first formatter that can serialize the type.

如果仍無比對,内容協商器便簡單地撿取能夠對類型進行序列化的第一個格式化器。

After a formatter is selected, the content negotiator chooses the best character encoding. by looking at the SupportedEncodings property on the formatter, and matching it against the Accept-Charset header in the request (if any).

在選擇格式化器之後,内容協商器會選擇最佳字元編碼。通過考察格式化器的SupportedEncodings,并根據請求的報送對其進行比對(如果有)。

你的推薦是我繼續下去的動力,也會讓更多人關注并獲益,這也是你的貢獻。

繼續閱讀