ASP .NET Core Web API_ 08_REST

什么是REST

REST 是 Representational State Transfer 的缩写. 它是一种架构的风格, 这种风格基于一套预定义的规则, 这些规则描述了网络资源是如何定义和寻址的.
一个实现了REST这些规则的服务就叫做RESTful的服务.

REST的原则/约束

REST有6大原则/约束, 每一个原则都是对API有正面或负面影响的设计决定.
RESTful API 最关心的有这几方面: 性能, 可扩展性, 简洁性, 互操作性, 通讯可见性, 组件便携性和可靠性.
这些方面被封装在REST的6个原则里, 它们是:

  1. 客服端-服务端约束: 客户端和服务端是分离的, 它们可以独自的进化.
  2. 无状态: 客户端和服务段的通信必须是无状态的, 状态应包含在请求里的. 也就是说请求里要包含服务端需要的所有的信息, 以便服务端可以理解请求并可以创造上下文.
  3. 分层系统: 就像其它的软件架构一样, REST也需要分层结构, 但是不允许某层直接访问不相邻的层.
  4. 统一接口: 这里分为4点, 他们是: 资源标识符(URI), 资源的操作(也就是方法Method, HTTP动词), 自描述的响应(可以认为是媒体类型Media-Type), 以及状态管理(超媒体作为应用状态的引擎 HATEOAS, Hypermedia as the Engine of Application State).
  5. 缓存: 缓存约束派生于无状态约束, 它要求从服务端返回的响应必须明确表明是可缓存的还是不可缓存的.
  6. 按需编码: 这允许客户端可以从服务端访问特定的资源而无须知晓如何处理它们. 服务端可以扩展或自定义客户端的功能.

只有满足了这6个原则的系统才可以真正称得上是RESTful的, 其实大部分系统的RESTful API并不是RESTful的, 但这样并不代表这些API就不好, 利弊需要开发人员去衡量.

# Richardson 成熟度模型

Richardson 成熟度模型代表着你的API是否足够成熟, 分为4个级别, 0代表最差, 3代表最好.

  • 0级, Plain Old XML沼泽:
    这里HTTP协议只是被用来进行远程交互, 协议的其余部分都用错了, 都是RPC风格的实现(例如SOAP, 尤其是使用WCF的时候).
    例如:
    POST (查询数据信息)
    http://host/myapi
    POST (创建数据)
    http://host/myapi

  • 1级, 资源:
    这级里, 每个资源都映射到一个URI上了, 但是HTTP方法并没有正确的使用, 结果的复杂度不算太高.
    例如这两个查询:
    POST
    http://host/api/authors
    POST
    http://host/api/authors/{id}

  • 2级, 动词:
    正确使用了HTTP动词, 状态码也正确的使用了, 同时也去掉了不必要的变种.
    例如:
    GET
    http://host/api/authors
    Ok (authors)
    POST (author representation)
    http://host/api/authors
    Created (author)

  • 3级, 超媒体:
    API支持超媒体作为应用状态的引擎 HATEOAS, Hypermedia as the Engine of Application State, 引入了可发现性.
    例如:
    GET
    http://host/api/authors
    200 Ok (返回了authors 和 驱动应用程序的超链接)

API 资源命名

  1. 资源应该使用名词, 它是个东西, 不是动作
    GET api/users 就是正确的
    GET api/users/{userId}.
  2. 层次结构
    例如 api/department/{departmentId}/emoloyees, 这就表示了department (部门)和员工(employee)之前是主从关系.
    api/department/{departmentId}/emoloyees/{employeeId}, 就表示了该部门下的某个员工.
  3. 过滤排序
    过滤和排序, 不是资源, 应作为参数.例如 api/users?orderby=username
  4. ID
    资源的URI应该永远都是一样的.
    推荐GUID应该作为ID来使用.
    自增int类型的ID, 在迁移到新数据库时需要特殊设定, 保证ID值不会发生变化.

HTTP方法与资源交互

HTTP

注意:

  • HEAD: 和GET差不多, 但是它不应该返回响应的body, 所以没有响应的payload. 它主要使用来获取资源的一些信息, 例如查看资源是否可用等.
  • OPTIONS: 它是用来查询某个资源URI的可交互方式有哪些, 换句话说就是, 使用它可以知道某个URI是否可以执行GET或者POST动作, 这些结果通常是在响应的Headers里面而不是body里, 所以也没有响应的payload.

状态码

  1. 状态码会告诉API的消费者:
    • 请求是否如预期的成功,或者失败
    • 如果出现了错误,谁该为这个错误负责
  2. API主要用到:
    • 200级别, 表示成功.
      * 200 - OK
      * 201 - Created,表示资源创建成功了
      * 204 - No content,成功执行,但是不应该返回任何东西
    • 400级别, 表示客户端引起的错误.
      * 400 - Bad request,表示API的消费者发送到服务器的请求是错误的
      * 401 - Unauthorized,表示没有权限
      * 403 - Forbidden,表示用户验证成功,但是该用户仍然无法访问该资源
      * 404 - Not found,表示请求的资源不存在
      * 405 - Method not allowed,这就是当我们尝试发送请求给某个资源时,使用的HTTP方法却是不允许的,例如使用POST api/countries, 而该资源只实现了 GET,所以POST不被允许
      * 406 - Not acceptable,这里涉及到了media type,例如API消费者请求的是application/xml格式的media type,而API只支持application/json
      * 409 - Conflict,表示该请求无法完成,因为请求与当前资源的状态有冲突,例如你编辑某个资源数据以后,该资源又被其它人更新了,这时你再PUT你的数据就会出现409错误;有时也用在尝试创建资源时该资源已存在的情况。
      * 415 - Unsupported media type,这个和406正好返回来,比如说我向服务器提交数据的media type是xml的,而服务器只支持json,那么就会返回415
      * 422 - Unprocessable entity,表示请求的格式没问题,但是语义有错误,例如实体验证错误。
    • 500级别, 表示服务器错误.
      * 500 - Internal server error,这表示是服务器发生了错误

HTTP GET

  • 单个数据
    找到了: 200
    没找到: 404
  [HttpGet("{id}")]
        public async Task<IActionResult> Get(int id)
        {
            var post = await _postRepository.GetPostByIdAsync(id);
            if (post == null)
            {
                return NotFound();//404
            }
            var postResource = _mapper.Map<Post, PostResource>(post);
            return Ok(postResource); //200
        }
  • 集合数据
    至少有一条数据, 200
    没有数据, 也是200
 [HttpGet]
        public async Task<IActionResult> Get()
        {
            var posts = await _postRepository.GetAllPostsAsync();
            var postResources = _mapper.Map<IEnumerable<Post>, IEnumerable<PostResource>>(posts);
            return Ok(postResources);
        }

内容协商

如果资源支持多种展现格式,那么消费者可以选择它想要的格式

  • 在请求的Accept Header指定Media Type
    * application/json, application/xml
    * 若未指定, 返回默认 application/json
  • 请求的media type不可用时, 并且消费者不支持默认格式, 返回406
  • ASP.NET Core支持输出和输入两种格式化器.
    * 用于输出的media type放在Accept Header里, 表示客户端接受这种格式的输出.
    * 用于输入的media type放Content-Type Header里, 表示客户端传进来的数据是这种格式.
    * ReturnHttpNotAcceptable设为true, 就会返回406.
services.AddMvc(
   options=>
     {
         options.ReturnHttpNotAcceptable = true; //开启406
         options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
     });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • 一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式。”但是在要求详细讲述它所提出的各个约束,以及如...
    时待吾阅读 3,415评论 0 19
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,629评论 18 139
  • 通常在做分享的时候 都会去集成第三方SDK,友盟、极光等,需要花费一些时间,其实系统也自带了分享的控件给我们,今天...
    咋了爸爸阅读 6,165评论 5 1
  • 认识DOM DOM的英文全称是Document Object Model,即文档对象模型,DOM的作用在于它能够在...
    刘涤生阅读 320评论 0 0
  • Ubuntu 下开始准备编译比特币 Ubuntu 16.04.我是装在了虚拟机上,参考菜菜子的文章来配置的 聊聊比...
    孤随风阅读 6,171评论 1 2