【问题标题】:Which API route design conforms to best practices? [closed]哪种 API 路由设计符合最佳实践? [关闭]
【发布时间】:2016-02-09 16:49:27
【问题描述】:

在为一个用 C# 编写的 ASP.Net Web API 应用程序设计 RESTFul 的 URI 时,我发现自己陷入了困境,什么是最佳实践。

取下面的伪代码。

public class File{
 public int ID {get;set;}
 public string Name {get;set;
}

public class X {
 public int ID {get;set;}
 public string Name {get;set;}
 public List<File> Files {get;set;}
}

public class Y  {
 public int ID {get;set;}
 public string Name {get;set;}
 public List<File> Files {get;set;}
}

public class Z  {
 public int ID {get;set;}
 public string Name {get;set;}
 public List<File> Files {get;set;}
}

现在,如果我想要一个特定的文件,我会调用类似:

/api/Files/{ID}

现在,如果我想要与另一个资源相关的文件,我是否要创建路由:

/api/X/{xID}/Files
/api/Y/{yID}/Files
/api/Z/{zID}/Files

或者我是否可以这样做:

/api/Files/X/{xID}
/api/Files/Y/{yID}
/api/Files/Z/{zID}

在维护方面,后一种选择似乎更合适;与文件有关的任何内容都包含在同一个控制器中。

虽然前一个选项对我来说似乎更明确,但不知何故,这意味着在整个控制器中传播类似的调用

或者,有什么不同的方法可以解决吗?

【问题讨论】:

  • 由于类没有封装任何不同类型的数据,是否有理由不使用或不能使用具有附加属性的单个总体信息类,该属性可以标记它是否为 X 、Y 还是 Z?
  • 也许,虽然这是主要问题的一个非常普遍的例子 - 那么当一个新类 W 进来并有一个 P 列表并且每个 P 都是文件时会发生什么 -如果你明白我的意思。猜猜我追求的是最佳实践。我想要这个文件,但有一个 X id - 我该往哪边走……
  • 这个意见的依据是什么??和downvote?有最佳实践,我不确定它们是什么......
  • @Darren,它并不是真正基于意见的,但社区中的一部分人认为 stackoverflow 不是问答网站。我将尝试在后续评论中提供我的答案,因为我无法提供“答案”
  • @Darren 根据经验,您的资源接口不一定与它下面的实现细节相匹配。您的问题的非答案是,它实际上取决于您尝试在服务墙上展示哪种交互模型。您的域的这个区域是更面向文件还是更面向“X、Y 和 Z”?对此的答案将回答您的主要问题,即“文件”是否位于您的“X、Y、Z”下方,或者您的“X、Y、Z”是否位于“文件”下方。如果你是从内到外设计这个而不是“到服务”和“到服务”......

标签: c# rest asp.net-web-api restful-url


【解决方案1】:

有许多指南解释了如何设计 API 的一些最佳实践。归根结底,设计者需要提供一个适合开发者的 API。

在这种情况下,您谈论的是两个不同的端点:(1) Files 端点,以及 (2) 包含文件的其他一些资源(我们称之为 Folders)。

一般而言,您的 URL 应包含 API 的版本(例如“v1”)和资源端点(例如“文件”)。因此,您的 URL 将形成如下:

1. /api/v1/files
2. /api/v1/folders

对于查询,您需要确保坚持使用一些标准的查询字符串参数(例如/api/v1/files?id=blah),而不是用斜杠或其他字符分隔查询参数。

对于另一个端点 (folders),在初始 get 中包含文件(或至少是标识符)可能是有意义的,或者要求调用者请求特定的 @ 可能是有意义的987654330@ out of the set 在提供此信息之前。

当开发人员想要在folder 中获取files 时,通过要求开发人员找出复杂的 URL 来拆分对象是不合适的。如果在查询folder 时不希望包含files,那么最好关闭关系并允许客户端使用查询在给定的folder 内查询files files 端点上的字符串语法。

一些有用的链接:

【讨论】:

  • 那么,你为什么要使用 id=.. 和 /{id} 呢?我读过的几乎所有资源都指的是后者——在处理主键 (id) 时,除非你从规范中搜索特定的东西,例如名称与 ID。参考版本;是的,我用它——我写了伪代码:)
  • 你可以,只要那是唯一的唯一标识符。我发现查询参数的方式比较清晰,但后者足够常见。
  • 更多情况下不是这样,在我使用过的大多数系统中也是如此
  • @Darren 作为风格问题,我更喜欢同时支持/{id}?id={id} 路径机制用于指定“id”是你真正的东西的中间标识符在一些分层数据中寻找,?id={id} 用于指定“这是我想要的东西”。查询段用于在路径表示的上下文中识别资源。路径段用于识别层次结构中的资源。
【解决方案2】:

我认为这是使用 json 引用的情况

http://json-spec.readthedocs.org/en/latest/reference.html

我不确定这个例子是否特别清楚,但本质上你提供了 /Files/fileId 接口,然后在你的 X/Y/Z 对象中而不是包含你引用它的文件

{
    "Files" : [{"$ref" : "/file/myFileId"}]
}

如果你想提供一个返回多个未分组资源的接口,恭喜你遇到了 REST 的限制,请使用 POST

----重新计算:

详细说明“使用 POST”

RESTful 方法是使用 GET 来“获取”资源,但是,当您必须传递多个 id 时,即 GET Files?id=1&id=2&id=3..... 您会遇到 url 的长度限制.这会迫使您使用 POST Files BODY id=1&id=2&id=3..... (或者更可能是一些 json 请求结构)关于这个主题有几个类似的问题,关于堆栈溢出的各种方法

【讨论】:

  • 几件事。 “使用 POST”而不是“REST”? REST 是一种架构风格,而 POST 是 HTTP 动词之一。您将在 RESTful 系统中使用 POST 请求。也不确定我是否同意 JSON 引用,因为 JSON 只是表示对象的一种方式,而不是实际访问资源的方式。不过谢谢你的回答:)
  • 我想从你的问题中脱颖而出的事情是为什么 GET X/{id} 不会将 X 的所有子文件作为 json 序列化对象的一部分返回给你?我的假设是它们会使它变得太大,或者您可能已经从 Y/{id} 请求中获得了它们。因此参考推荐
猜你喜欢
  • 1970-01-01
  • 2020-04-23
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 2011-08-14
  • 2018-07-09
相关资源
最近更新 更多