我有两个简单的问题,我只是想得到社区的意见 -
如果我有一个可以使用ID或日期(20110705)访问的实体,那么用于访问该实体的url约定的最佳做法是什么?
获取:/myEntities/{date}
和/myEntities/{id}
? (哪个
service将解析{object}以检查它是日期还是id。
获取:/myEntities/date/{date}
和/myEntities/id/{id}
*?
在WCF Rest中,我也可以/myEntities/?date={date}
和/myEntities/?id={id}
,这是REST的一个很好的做法吗?换句话说,就最佳做法而言,使用?date={date}
代替date/{date}/
是否可以接受,因为它只是个人偏好?
提前致谢。
答案 0 :(得分:8)
我觉得这很大程度上取决于偏好和风格。
话虽如此,我个人更喜欢:
/myEntities/date/{date}
和/myEntities/{id}
无需明确ID选项;这是假设的。
关于#2;我个人不喜欢这种语法:/myEntities/?date={date}
如果它在WCF中作为URI模板实现 - 因为如果您有多个参数,则假设参数的顺序可以被推挤周围 - 但他们不能与URI模板。但是,作为标准的查询字符串参数,这是完全可以接受的,并且在各地都可以完成 - 谷歌,雅虎,亚马逊和其他人都使用这种风格。
如果有的话,这正是“查询字符串”的意思 - 查询的参数......这正是您在通过 __ 检索实体时所做的事情。
(但我和其他人会说的一样好奇。)
答案 1 :(得分:6)
/myEntities/date/{date}
应根据您的应用使用301或307重定向到/myEntities/{id}
。这减少了由于多个缓存副本导致数据不同步的可能性,并使客户明白/myEntities/date/*
只是一个备用索引,而不是一组独立资源(正如他们可能正确期望的那样)由于HTTP URI的分层特性,因此不重定向。
答案 2 :(得分:0)
资源有一个标识URL(如果您愿意,则为自己的URL)。这绝不能改变。这也意味着,如果您冒险在某一点更改该ID,那么该ID不是您在网址中使用的ID。如果您冒险回收id,那么您绝对不应该使用该ID。
这也意味着,您永远不会有两个唯一标识相同资源的网址。
现在这并不意味着您无法从两个不同的网址访问相同的资源。你想要这样做有很多原因。您需要确定一些事项。
对于任何消费你API的人来说,你应该很容易理解它。您列出的选项不会这样做。
它基本上归结为建模,并确保您的内部模型不会流入公共API。您可能有一个重载方法可以将id或日期作为输入参数,这并不意味着您应该公开该重载。
因此,问问自己这两种情况中的每种情况都会解决,然后它可能会变得明显。
我也不喜欢史蒂夫的建议。消费者如何知道您可以写“日期”而不是ID,然后突然按日期访问?这不直观。
因此,问问自己能否将日期用作网址的一部分,或者将其作为查询字符串过滤器添加到集合上是否最重要。这样你就可以实际公开一个往返日期过滤器,这可能更具价值,也更直观。
或者考虑以下内容:
/years
可能会公开年份对象列表
{
"year": 2015,
"entities": "https://api.myapp.com/years/2015/entities",
"months": [
{
"month": 1,
"name": "January",
"entities": "https://api.myapp.com/years/2015/months/1/entities",
"self": "https://api.myapp.com/years/2015/months/1"
},
... array of month objects
],
"self": "https://api.myapp.com/years/2015"
}
/years/2015/months/1
是月份对象的一个示例
{
"month": 1,
"name": "January",
"entities": "https://api.myapp.com/years/2015/months/1/entities",
"self": "https://api.myapp.com/years/2015/months/1"
}
entities属性具有指向按日期过滤的实体集合的链接。
但这又取决于你的具体问题。只需记住使界面直观,不要让你的内部建模流入你的公共API。但这根本不是一件容易的事。