包含相关资源的RESTful API

时间:2016-08-29 16:06:06

标签: javascript c# rest api wcf

我正在设计我的第一个严肃的RESTful API,它将位于WCF服务之上。

有资源如;出口,日程安排和工作。时间表始终由商店拥有,并且时间表将包含0个或更多个工作。工作不必按计划进行。

我一直认为资源应该以与文件系统上的资源相同的方式寻址。这意味着我会像URI一样:

/outlets
/outlets/4/schedules
/outlets/4/schedules/1000/jobs
/outlets/4/schedules/1000/jobs/5123

尽管在考虑如何在不同情况下回收资源时,事情开始变得混乱。

e.g。我想要一份不按时安排的工作:

/outlets/4/jobs/85(现在这意味着我们有两种方法可以按计划完成工作)

e.g。我想要所有的时间表,无论出口如何:

/schedules/outlets/ALL/schedules

还有许多其他更复杂的要求,但我确信你得到了要点。

文件系统具有良好,合理的资源寻址方式。显然,您可以创建符号链接并获得与我描述的内容相似的内容,但它会变得混乱。一旦事情变得更加复杂,它就会变得更加混乱,例如增加按日期获取时间表的能力:

/outlets/4/2016-08-29/schedules

在不使用查询字符串参数的情况下,我甚至不确定如何请求所有不按计划进行的作业。以下错误是因为unscheduled不是资源:

/outlets/4/unscheduled/jobs

所以,我认为文件系统类型寻址只适用于最简单的服务(我们的底层系统有数百种实体类型,有一些非常复杂的关系和大量的操作)

有多种方法做同样的事情往往会导致混乱和文档混乱,我想避免它。因此,我几乎不得不选择使用最低的公分母并选择非常简单的地址表格 - 如下面的第3个:

/outlets/4/schedules/1000/jobs/5123
/outlets/4/jobs/5123
/jobs/5123

从这些非常简单的地址表单中,我需要使用查询字符串参数进行扩展,以执行更复杂的操作,例如:

/jobs?scheduleId=1000
/jobs?outletId=4
/jobs?outletId=4&fromDate=2016-01-01&toDate=2016-01-31

这感觉就像它违反REST模型一样,查询这样的字符串参数是不可预测的,所以到目前为止还没有文档需要"理念。

好的,所以,在我想要获得干净,可维护的API的时候,我几乎就在围栏的一边,我将不得不使用非常简单的资源地址,使用广泛地查询字符串参数并具有良好的文档。

无论如何,这并不是我应该得出的结论。我哪里出错了?

1 个答案:

答案 0 :(得分:0)

欢迎来到REST API编程世界。这些是我们在尝试将一般原则应用于特定情况时所面临的难题。您的问题没有明确而简单的答案,但这里有一些可能有用的其他提示。

首先,你是正确的,当你有复杂的关系时,文件系统的解决方法就会崩溃。当那里有一个真正的层次结构时,你只想建立那种寻址。

例如,如果所有作业都是单个计划的一部分,那么查看schedules/{id}/jobs/{id}来获取给定作业是有意义的。如果从数据存储的角度考虑它,您可以想象每个计划都有一个XML文件,而作业只是该文件中的元素。

但是,听起来在这种特殊情况下,您的数据更多是关系。从数据存储的角度来看,您将每个作业表示为数据库表中的一行,并建立一些外键关系以将某些作业绑定到某些计划。您的寻址方案应该通过使/jobs成为顶级端点,并使用可选的查询字符串参数按计划或出口进行过滤来反映这一点。

所以你正走在正确的轨道上。您可能还需要考虑的另一件事是OData,它扩展了基本的REST原则,采用了面向标准的方式来表示诸如使用查询字符串参数进行过滤。地址语法感觉有点"在那里",但它在处理直接REST开始崩溃的情况方面做得相当不错。而且由于它更加标准化,因此可以使用一些工具来帮助完成从数据层转换为OData端点,或者根据该端点公开的元数据生成客户端代理帮助程序。

  

这感觉就像它违反REST模型一样,查询这样的字符串参数是不可预测的,所以到目前为止还没有文档需要"想法。

如果您使用OData,那么其规范会与您的工具生成的元数据相结合,成为您的文档。例如,您的元数据表明job具有代表日期的date属性。然后OData规范提供了一种表示日期值的过滤查询的方法。根据这些信息,消费者可以可靠地生成一个过滤查询,该过滤查询只会“正常工作”。因为您正在使用框架服务器端来执行硬件。如果他们不想记住OData URL的工作方式,他们可以用自己选择的语言生成客户端代理,这样他们就可以通过自己喜欢的语法生成相应的URL。