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

简介: 原文:Asp.Net Web API 2第十四课——Content Negotiation(内容协商)前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET Web API如何实现内容协商。
原文: 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,并根据请求的报送对其进行匹配(如果有)。

目录
相关文章
|
9天前
|
开发框架 监控 .NET
Visual Basic的Web服务和REST API开发指南
【4月更文挑战第27天】本文探讨了使用Visual Basic(VB.NET)构建Web服务和RESTful API的方法。首先介绍了Web服务的基础和REST API的概念,然后阐述了.NET Framework与.NET Core/.NET 5+对VB.NET的支持,以及ASP.NET Core在Web开发中的作用。接着,详细讲解了创建RESTful API的步骤,包括控制器与路由设置、模型绑定与验证,以及返回响应。此外,还讨论了安全措施、测试方法、部署选项和监控策略。最后强调,VB.NET开发者可以通过ASP.NET Core涉足现代Web服务开发,拓宽技术领域。
|
27天前
|
API 网络安全 数据安全/隐私保护
.NET邮箱API发送邮件的方法有哪些
本文介绍了.NET开发中使用邮箱API发送邮件的方法,包括SmtpClient类发送邮件、MailMessage类创建邮件消息、设置SmtpClient属性、同步/异步发送、错误处理、发送HTML格式邮件、带附件邮件以及多人邮件。AokSend提供高触达发信服务,适用于大规模验证码发送场景。了解这些技巧有助于开发者实现高效、可靠的邮件功能。
|
5天前
|
弹性计算 JSON Shell
基于Web API的自动化信息收集和整理
【4月更文挑战第30天】
13 0
|
9天前
|
开发框架 缓存 前端开发
利用Visual Basic构建高效的ASP.NET Web应用
【4月更文挑战第27天】本文探讨使用Visual Basic与ASP.NET创建高效Web应用的策略,包括了解两者基础、项目规划、MVC架构、数据访问与缓存、代码优化、异步编程、安全性、测试及部署维护。通过这些步骤,开发者能构建出快速、可靠且安全的Web应用,适应不断进步的技术环境。
|
10天前
|
缓存 前端开发 API
toapi,一个强大的 Python Web API库!
toapi,一个强大的 Python Web API库!
24 5
|
18天前
|
JSON API 数据库
解释如何在 Python 中实现 Web 服务(RESTful API)。
在Python中实现Web服务(RESTful API)涉及选择框架(如Flask、Django、FastAPI),定义路由及处理函数(对应HTTP请求方法),处理请求,构建响应和启动服务器。以下是一个使用Flask的简单示例:定义用户列表,通过`@app.route`装饰器设置GET和POST请求处理函数,返回JSON响应,并用`app.run()`启动服务器。实际API会包含更复杂的逻辑和错误处理。
15 1
|
2月前
|
XML JSON API
通过Flask框架创建灵活的、可扩展的Web Restful API服务
通过Flask框架创建灵活的、可扩展的Web Restful API服务
|
2月前
|
缓存 监控 API
Python Web框架FastAPI——一个比Flask和Tornada更高性能的API框架
Python Web框架FastAPI——一个比Flask和Tornada更高性能的API框架
60 0
|
2月前
|
JSON API 数据格式
构建高效Python Web应用:Flask框架与RESTful API设计实践
【2月更文挑战第17天】在现代Web开发中,轻量级框架与RESTful API设计成为了提升应用性能和可维护性的关键。本文将深入探讨如何使用Python的Flask框架来构建高效的Web服务,并通过具体实例分析RESTful API的设计原则及其实现过程。我们将从基本的应用架构出发,逐步介绍如何利用Flask的灵活性进行模块化开发,并结合请求处理、数据验证以及安全性考虑,打造出一个既符合标准又易于扩展的Web应用。
674 4
|
3月前
|
前端开发 JavaScript API
前端秘法番外篇----学完Web API,前端才能算真正的入门
前端秘法番外篇----学完Web API,前端才能算真正的入门