Asp.Net Web API 2第十四課——Content Negotiation(內容協商)

來源:互聯網
上載者:User

標籤:

前言

閱讀本文之前,您也可以到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.1Host: localhost.:21069Accept: application/json, text/javascript, */*; q=0.01

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

HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8Content-Length: 57Connection: 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,並根據請求的報送對其進行匹配(如果有)。

Asp.Net Web API 2第十四課——Content Negotiation(內容協商)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.