Asp.net Web Api 设计 [持续更新]

第一部分 基础知识

第一章 因特网、万维网和HTTP协议

1.1 Web体系结构

Web体系有三个核心概念:资源 、URL和表示。一个资源由一个URI进行标识,而HTTP客户端使用URI就可定位资源。表示是从资源返回的那些数据。和Web相关的另-一个重要概念是媒体类型(media type),指的是从资源返回数据的格式。

1.1.1 资源

任何带有URL 标识的东西都是资源。一个网页一个文档或者是一个文件都是资源,而资源不仅限于这些,它也可以是一个建立连接的服务。也可以是一个媒体流声音流。

资源必须关联实体或者数据库吗?
现在,人们对于Web API有一一个常见的误解,认为一个资源必须对应到一个有数据库支持的实体或者业务对象。在讨论设计时经常会有人说:“我们不能用这个资源,因为这个资源需要在数据库中创建一个表,而我们又不需要这张表。”前面给出的资源定义中描述了到一个或多个实体的映射,这里所说的实体是泛指的(也就是说,实体可以是任何东西),而不是特指业务对象。一个应用程序可以这样设计,让其中提供的资源总是映射到业务实体或数据库表,对这种系统而言,前面那种说法确实是正确的。但是,这种限制是由应用或框架强加的,Web API本身并没有这种限制。
在构建Web API时,这种实体/资源的限制在很多情况下会导致问题。例如,一个订单处理资源,在处理一个订单时实际上会统筹实施不同的系统。在这种情况下,执行这个资源会调用系统的几个部分,这些部分会各自在数据库中存储状态,而这个资源自身可能在数据库中存储状态,也可能不存。问题的关键是,这个资源在数据库中没有直接对应关系。并且,被调用的各个组件也并不一定要使用数据库(虽然在前面例子中是使用了数据库的)。

在设计Web API时,请记住上述区别,这可以帮助你在系统中真正发挥Web的力量。

1.2.4 中间件

参与HTTP消息交换并对客户端可见的中间层有三种。
代理(proxy), 它代表客户端发出HTTP请求并接受响应。客户端使用代理时采用主动模式,需要进行相应的配置。很多组织都会使用内部代理,组织内的用户必须通过这个代理访问因特网,这种做法非常普遍。如果-一个 代理有意对HTTP请求或者响应进行修改,那么这个代理就是转化代理(transforming proxy)。不修改消息的代理称为非转化代理(non transforming proxy)。
网关(gateway)接受传入的HTTP消息,将其翻译为服务器底层的协议,底层协议可能是HTTP,也可能不是HTTP。网关也处理传出的消息,将其转化为HTTP协议。网关可以代表源服务器处理请求。
隧道(tunnel) 在两个连接之间建立一个私有通道,不会修改任何消息。隧道的-一个例子是两个客户端穿过防火墙用HTTPS进行通信。

CND是中间件吗?

另一种常见的因特网缓存机制是CDN (Content Delivery Network,内容分发网络)。
CDN是一组分散的机器,缓存和返回静态内容。市场上有很多流行的CDN服务商,如Akamai (http://www.akamai.com/), 为公司提供内容缓存。那么,CDN是中间层吗?答案取决于内容请求是怎样传递给CDN的。如果客户端直接向CDN发出请求,那么CDN扮演的是源服务器的角色。有些CDN功能类似于网关,对客户端是不可见的,但它实际上代表源服务器进行操作,缓存并返回所请求的内容。

1.2.5 HTTP方法

GET
从资源获取信息。如果返回资源,服务器应该返回状态码200 (OK)。
HEAD
与GET相同,但返回标头而非主体。
POST
请求服务器接受消息中包含的实体,交由目标资源处理。作为请求处理过程的一部分,服务器可以创建一个新的资源,但不--定如此。如果服务器创建了资源,那么应该返回状态码201 (Created) 或者202 (Accepted), 并返回-一个地址标头,告知客户端从何处访问新资源。如果服务器没有创建资源,那么应该返回状态码200 (OK) 或者204 (NoContent)。在实际应用中,POST 方法基本上可以进行任何类型的处理,不受任何限制。
PUT
请求服务器将指定URI所代表的目标资源替换为消息中包含的实体。如果当前表示对应的资源存在,服务器应该返回状态码200 (OK) 或者204 (No Content)。 如果对应的资源不存在,那么服务器可以创建这个资源。如果服务器创建了资源,应该返回状态码201 (Created)。 POST 和PUT的主要区别在于: POST 方法预期数据被传入加工,而PUT方法预期数据被替换或者存储。
DELETE
请求服务器移除指定URI所代表的实体。如果服务器立即移除了指定的资源,那么应该返回状态码200(OK)。如果资源尚未移除,那么服务器应该返回状态码202(Accepted)或者204 (No Conent)。
OPTIONS
请求服务器返回功能信息。大多数情况下,服务器返回一个Allow标头,具体说明支持哪些HTTP方法,尽管协议规范对此并没有硬性规定。例如:服务器完全可以列出支持哪些媒体类型。OPTIONS 方法也可以返回-一个正文,提供在标头内无法表示的更多信息。
PATCH
请求服务器对指定URI所代表的实体进行部分更新。PATCH方法中应该包含足够的信息,供服务器进行所请求的更新。如果指定的资源存在,服务器可以进行更新并返回状态码200 (0K) 或者204 (No Content)。 与PUT的处理方法类似,如果指定的资源不存在,服务器可以创建这个资源。如果服务器创建了资源,就应该返回状态码201(Created)。如果- -个资源支持PATCH方法,那么OPTIONS响应的Allow标头可以对此进行说明。服务器也可以使用Accept-Patch标头,列出客户端可以对其发送PATCH请求的媒体类型。协议规范建议媒体类型应包含语义,向服务器传递部分更新所需的信息。
json-patch ( 参见htps://olsietf.org/htmo/drfaf/pbryan-json-patch-04)是-一个提议的媒体类型草案,支持表达部分更新中所需的操作。

TRACE
请求服务器返回其收到的请求。服务器返回-一个content- type为message/http的正文,其中包含完整的请求信息。客户端可以使用TRACE方法,查看请求消息经过的代理以及中间层对消息所做的修改,有助于进行问题诊断。

第二章 Web Api

2.1 什么是Web Api

Web API是一个编程接口,用于操作可通过标准HTTP方法和标头访问的系统。Web API可供各种HTTP客户端使用,如浏览器和移动设备,并可以使用Web基础设施提供的服务,如缓存和并发。

2.6 Web Api 指南

Web Api 特点

● 可供多种客户端使用(至少支持浏览器使用)。
● 支持标准的HTTP方法,如表1-1中列举的方法。API 不 必使用全部的HTTP方法,但是,至少应该支持 GET以获取资源,还应支持POST 以进行非安 全操作。
● 支持浏览器友好的格式。也就是说,Web API支持 浏览器以及任何其他HTTP客户端容易处理的格 式。在技术上,浏览器客户端可 以使用XML 栈处理SOAP消息,但在格式上需要编写大量的专 门]用于处理SOAP的代码。浏览器容易处理的格式 有: XHMTL、JSON 以及Form URL编码。
● 支持浏览器友好的认证方式。也就是说,浏览器 无需使用特殊的插件或扩展,就可以与服务器进 行认证。

第三章 Asp.Net Web Api

写一个访问Api的例子

public class GreetingController : ApiController
{
    public string  GetGreeting()
    {
        return "hello world";
    }
    public static List<Greeting> _greetings = new List<Greeting>();
    public HttpResponseMessage PostGreeting(Greeting greeting)
    {
        _greetings.Add(greeting);
        var greentingLocation = new Uri(this.Request.RequestUri, "greeting/greeting.Name);
        var response = this.Request.CreateResponse(HttpStatusCode.Created);
        response.Headers.Location = greentingLocation;
        return response;
    }

    public string GetGreeting(string id)
    {
        var greeting = _greetings.FirstOrDefault(g => g.Name == id);
        if(greeting == null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
        return greeting.Message;
    }

    /// <summary>
        /// 测试
        /// </summary>
    [Fact]
    public void TestNewGreetingAdd()
    {
        //准备
        var greetingName = "newgreetring";
        var greetingMessage = "hello Test";
        var fakeRequest = new HttpRequestMessage(HttpMethod.Post, https://localhost:44382/api/greeting");
        var greeting = new Greeting
        {
            Name = greetingName,
            Message = greetingMessage
        };
        var service = new GreetingController();
        service.Request = fakeRequest;

        //操作
        var response = service.PostGreeting(greeting);

        //断言
        Assert.NotNull(response);
        Assert.Equals(HttpStatusCode.Created, response.StatusCode);
        Assert.Equals(new Uri("https://localhost:44382/api/greeting/newgreeting"), response.Headers.Location);
    }

再写一个控制台调用api

 static void Main(string[] args)
 {
     var greetingServiceAddress = new Uri("https://localhost:44382/api/greeting");
     var client = new HttpClient();
     var result = client.GetAsync(greetingServiceAddress).Result;
     var greeting = result.Content.ReadAsStringAsync().Result;
     Console.WriteLine(greeting);
     Console.ReadLine();
 }
posted @ 2020-02-01 23:53  乾子  阅读(492)  评论(0编辑  收藏  举报