天天看點

ASP.NET WebAPI中内容協商1、内容協商的定義2、内容協商工作方式3、自定義内容協商4、總結

目錄

  • 1、内容協商的定義
  • 2、内容協商工作方式
  • 3、自定義内容協商
  • 4、總結

1、内容協商的定義

1、内容協商(Content Negotiation)的定義是:

當存在多個表示形式時,為給定響應選擇最佳表示形式的過程

。也就是說

Request

請求可接受

xml

json

text

等格式的内容,選擇哪種最合适,并傳回給請求的過程就是

内容協商

2、内容協商的主要依據是request請求中的:

Accept

Accept-Charset

Accept-Encoding

Accept-Language

。一個典型的request請求如下:

GET /webapidemo/api/products/getResponseMessage HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh,zh-CN;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
           

而内容協商就是根據request中提到的header,決定最後的響應方式。

最後響應如下:

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Date: Tue, 13 Apr 2021 07:56:22 GMT
Content-Length: 82
           

通過對request中accept中最優的選擇,進行了響應。這就是内容協商。

2、内容協商工作方式

1、管道從

HttpConfiguration

對象中擷取

内容協商執行個體對象

、支援的媒體格式清單

2、管道調用

内容協商執行個體對象

Negotiate

方法,并傳入:

要序列化的對象(即傳回給用戶端的資料對象)

Request

媒體格式清單

3、

内容協商執行個體對象

Negotiate

方法,傳回一個

ContentNegotiationResult對象

。而這個對象中包含了:使用哪種格式化程式和要響應的媒體類型

下面的代碼示範了如何直接調用内容協商

public HttpResponseMessage GetProduct(int id)
{
    var product = new Product() 
        { Id = id, Name = "Gizmo", Category = "Widgets", Price = 1.99M };

	//通過HttpConfiguration對象擷取内容協商對象
    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,		        //需要序列化的對象
            result.Formatter,           //序列化格式器
            result.MediaType.MediaType  //媒體類型
        )
    };
}
           

本質上,内容協商就是一個序列化格式器的選擇程式。

3、自定義内容協商

了解了内容協商,可以看一下如何自定義内容協商

public class JsonContentNegotiator : IContentNegotiator
{
    private readonly JsonMediaTypeFormatter _jsonFormatter; //使用系統自帶的格式化器(本質是一個序列化程式)

    public JsonContentNegotiator(JsonMediaTypeFormatter formatter) 
    {
        _jsonFormatter = formatter;    
    }

	//傳入參數,然後實作Negotiate方法
    public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
    {
        var result = new ContentNegotiationResult(_jsonFormatter, new MediaTypeHeaderValue("application/json"));
        return result;
    }
}

           

在配置檔案中,再将預設的替換掉

var jsonFormatter = new JsonMediaTypeFormatter();
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));

           

這樣就能夠實作了自定義内容協商。

以上自定義的方法中,隻是使用了系統自帶的json序列化器(系統自帶json和xml的序列器),若想自定義序列器,可參考MSDN的樣例:自定義序列器MSDN的說明

4、總結

本質上内容協商是一個根據請求中的accept,對發送給用戶端的資料,進行了指定格式的序列化的過程