为了与RESTful API进行交互,API消费者需要使用到三个概念:

  • 资源的标识。也就是可以找到资源的URI。

  • HTTP方法。例如GET,POST等等,这些方法是HTTP协议的一部分。

  • 有效载荷(可选),英文就是Payload。例如,当你想创建资源的时候,HTTP请求里面会包含着你想要创建的资源的一个表述。或者当获取资源的时候,HTTP响应里面会它的Body里面包含着资源的表述。这些表述的格式就是我们使用的media type,例如application/json。

之前讲了RESTful API的统一资源接口这个约束,里面提到了资源是通过URI来进行识别的,每个资源都有自己的URI。URI里还涉及到资源的名称,而针对资源的名称却没有一个标准来进行规范,但是业界还是有一些最佳实践的。那么我们首先看看这些最佳实践对资源命名是如何建议的。

资源命名

使用名词,而不是动词

一个资源的URI代表的是一个实际上或概念上存在的东西,因此,它应该是名词,所以也就不应该出现动词,动词应该使用HTTP方法来表达。

需求:我们看这样一个需求的例子:“我想获得系统里所有的用户”。

常见错误做法:你可能把API的URI设计成这样:api/getusers。这样的设计是不好的,因为里面出现了一个动词get。

分析:这个句话的主要动词就是“获取”,而想要获取的资源(也就是主要的名词)是“用户”。

正确的做法:需求里面主要的动词应该通过HTTP方法来体现,“获取”对应的HTTP方法就是GET。而“用户”这个资源可以用英文user或者users来表示(是否使用复数一直存在争议,两种方法都行,但你在使用的时候需要保持一致)。所以正确的uri应该是 GET api/user。

人类能读懂

还是上面那个需求:“我想获得系统里所有的用户”。

我们可以把uri设计成 api/u 或者 api/ur。但是这样设计的话,对API的消费者来说非常的不友好,因为不能直观的看出来它到底代表的是什么资源,可能是user,也可能是university。

所以建议的做法是要足够友好,并且比较简短,例如:api/users。

要体现资源的结构关系

假设如果后端API系统里面有若干种资源,而用户这个资源与其它的资源并没有直接的关系,这样的话获取用户资源的uri应该是 api/users。而不是 api/products/users,也不是api/catalogs/products/users,因为user和product或者catalog没有直接的关系。

通过id获取单个用户的uri应该是:api/users/{userId},而不是api/userid/users。

这样写的好处是可以让API具有很好的可预测性和一致性。

需求1:系统里有两类资源,公司(Company)和员工(Employee),它们俩是包含关系,也就是一个公司包含多个员工。现在我想获取某个公司下所有的员工信息。

分析:这里的主要动词还是“获取”,所以我们可以使用HTTP的GET。而这里的资源有两个,分别是公司和员工,而且它们是包含关系:一个公司包含多个员工或者说一个公司是一个员工的集合。所以API的URI在设计的时候需要体现这种包含关系。

常见的错误做法:如果你想获得公司这个资源,我想你现在应该不会出错,uri应该是 api/companies。而想要获取某个公司下的员工,常见的错误做法有:api/employees,api/employees/{companyId}等等。这些设计非常不好是因为它无法体现出Company和Employee之间的结构关系。

建议的做法:需要体现Company和Employee之间的关系,所以uri应该是GET api/companies/{companyId}/employees。这样做直接体现出了Company和Employee之间的结构关系,而且也体现出了一个Company就是一个Employee的集合体。

需求2:我想获取某个公司的某个员工信息。

常见的错误做法:api/employees/{employeeId},api/companies/{employeeId}等等。这些做法都无法体现出Company和Employee之间的关系。

建议的做法:api/companies/{companyId}/employees/{employeeId}。

自定义查询怎么命名

我们经常会遇到这样的需求,比如获取按照某个资源排序后的资源,或者按照某些条件过滤后的资源。这时候应该怎对资源进行命名呢?

需求:“我想获取所有的用户信息,并要求结果是按年龄从小到大进行排列的”。

常见错误的做法:api/users/orderby/age。之前说了,uri里面使用的都应该是名词,如果按照这个uri的结构来看,那么orderby和age就应该是另外两个资源,并且users包含orderby,orderby包含age,这显然是错误的。

建议的做法:api/users?orderby=name,这样设计更合理一些。这里使用了query string作为查询参数进行排序。

例外

有一些需求总是无法满足的达到RESTful的约束。

需求:“我想获取系统里所有用户的数量”。

妥协的做法:我们确实可以先通过 GET api/users来获取系统里所有的用户信息,然后再算出用户的数量,但是这样做也太浪费资源并且效率也太低了。我们也很难使用某个名词来表示这个需求的资源。例如:api/users/totalamountofuser。这样的uri按理说就代表着我们将会获取到一个集合资源,里面是一堆数字,但针对这个需求,我也没有特别好的办法让uri命名完全符合RESTful的约束,所以针对这个需求,我使用的就是这个uri。

Microsoft Learn的官方教程《使用 ASP.NET Core 创建 Web API》请点击原文链接。

使用ASP.NET Core 3.x 构建 RESTful API - 3.1 API资源命名相关推荐

  1. 【视频教程】使用 ASP.NET Core 3.x 构建 RESTful Web API 已完结

    使用 ASP.NET Core 3.x 构建 RESTful Web API 的视频教程已经完结,共50讲,约10.5小时. B站可看,点击原文链接. 度娘盘可下载完整视频: https://pan. ...

  2. 使用ASP.NET Core 3.x 构建 RESTful API - 2. 什么是RESTful API

    1. 使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作 什么是REST REST一词最早是在2000年,由Roy Fielding在他的博士论文<Archit ...

  3. 使用ASP.NET Core 3.x 构建 RESTful API - 1. 开始

    以前写过ASP.NET Core 2.x的REST API文章,今年再更新一下到3.0版本. 预备知识:ASP.NET Core 和 C# 工具:Visual Studio 2019最新版(VSCod ...

  4. 使用ASP.NET Core 3.x 构建 RESTful API - 4.2 过滤和搜索

    向Web API传递参数 数据可以通过多种方式来传给API. Binding Source Attributes 会告诉 Model 的绑定引擎从哪里找到绑定源. 共有以下六种 Binding Sou ...

  5. 使用ASP.NET Core 3.x 构建 RESTful API - 3.4 内容协商

    现在,当谈论起 RESTful Web API 的时候,人们总会想到 JSON.但是实际上,JSON 和 RESTful API 没有半毛钱关系,只不过 JSON 恰好是RESTful API 结果的 ...

  6. 使用ASP.NET Core 3.x 构建 RESTful API - 3.3.3 ProblemDetails

    当ASP.NET Core 大约在 2.1 版本的时候,它引入了 ProblemDetails.ProblemDetails是基于 RFC7807 这个规范,目的是让 HTTP 响应可以携带错误的详细 ...

  7. 使用ASP.NET Core 3.x 构建 RESTful API - 3.2 路由

    路由机制会把一个请求的URI映射到一个Controller上面的Action,所以当你发送一个HTTP请求的时候,MVC框架会解析这个请求的URI,并尝试着把它映射到一个Controller上面的Ac ...

  8. 使用ASP.NET Core 3.x 构建 RESTful API - 4.1 面向外部的Model

    Entity Framework Core 使用的 Entity Model 是用来表示数据库里面的记录的. 而面向外部的 model 则表示了要传输的东西.这类 model 有时候叫做 Dto,有时 ...

  9. 使用ASP.NET Core 3.x 构建 RESTful API - 3.2 开始建立Controller和Action

    Demo 下面我们就来实践一下.打开之前的项目,并建立CompaniesController: 这里有6个地方比较关键,我们挨个看一下: RESTful API 或者其它Web API的Control ...

最新文章

  1. Eclipse中SVN的安装步骤(两种)和使用方法 (转)
  2. LESSON 12.7 梯度提升树的参数空间与TPE优化
  3. SpringCloud教程-消息总线Bus 服务端(server)刷新(SpringCloud版本Greenwich.SR4)
  4. Conversion to Dalvik format failed with error 1解决方法:
  5. php 匹配图片路径_php正则匹配图片路径原理与方法
  6. .net 4 环境调用 .net 2 编译的DLL
  7. QT_Qsplitter
  8. 安卓导航车机root方法_远程调试在Linux车机中的应用
  9. java set集合与List集合练习
  10. php Immutable,Immutable.js详解
  11. HTML实现点击时的阴影(:active)(已解决iOS微信上无法使用)
  12. 基于PHP的在线聊天室(网页版)
  13. 信号处理:希尔伯特-黄变换
  14. 酸菜鱼,新一代微商暴富大机会?
  15. 银行统一支付平台(介绍、架构)
  16. 夫妻贷款买房需要注意什么
  17. APP的三种类型以及区分方法
  18. NVIDIA apex安装
  19. 十、RabbitMQ发布确认高级
  20. Handler 源码解析——Handler的创建

热门文章

  1. 《那些年啊,那些事——一个程序员的奋斗史》——126
  2. 在DataGrid中合并单元格行
  3. JavaScript 游动层onmouseover
  4. 如何在Windows 10上使用触摸板手势
  5. ios 轻扫手势_轻扫即可快速删除iOS计算器中的数字
  6. 如何用 Flutter 实现混合开发?闲鱼公开源代码实例
  7. Kotlin 基础 - 数据类型
  8. 聊聊storm nimbus的LeaderElector
  9. 2016年工作总结和计划
  10. 代码设置Shape和Selector