ASP.NET WebAPI中内容协商

1、内容协商的定义

1、内容协商(Content Negotiation)的定义是:当存在多个表示形式时,为给定响应选择最佳表示形式的过程。也就是说Request请求可接受xmljsontext等格式的内容,选择哪种最合适,并返回给请求的过程就是内容协商
2、内容协商的主要依据是request请求中的:AcceptAccept-CharsetAccept-EncodingAccept-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,对发送给客户端的数据,进行了指定格式的序列化的过程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值