Web API - REST 帮助和说明
Web API - REST help and clarification
我正在使用 WebAPI 编写 API,虽然我是从头开始设计它,但我正在努力实现它 RESTful。过去在做 Web 服务工作时,我总是使用 RPC 模式(ASMX、SOAP 等)——例如。使用与我想要它做的相匹配的任意方法名称。对我来说,这似乎比 REST 更直观和明确,但考虑到 WebApi 似乎更 RESTful 本质上(我知道你可以改变路线,所以它不是),我决定尝试制作它 RESTful.
我了解(我认为!)基础知识 - 例如。 POST创建,指定ID时PUT更新,GET获取,DELETE删除等
我的困惑是如何处理 returning 集合与单个对象。例如,假设我有一个名为 UsersController
的 API 控制器。据我所知,我有以下 URLs:
GET: /api/users (lists all users)
GET: /api/users/1 (lists details about user with ID 1)
POST: /api/users (creates a new user with details sent in the POST data)
PUT: /api/users/1 (updates the existing user with ID 1 with details sent in the POST data)
DELETE: /api/users/1 (deletes the existing user with ID 1)
对于上面的第一个 URL,我还需要发送各种 filter/search 条件。这个条件是否只是作为查询字符串参数传递?或者我应该为这个 "search" 功能使用完全不同的控制器吗?例如。用户搜索控制器?如果是这样,在这种情况下应该是 POST 还是 GET?事实上,在我写这篇文章时,我想知道一个单独的控制器是否有意义,因为我可能希望在 GET 中为单个用户提供比搜索结果更多的详细信息 return。如果同一个控制器对单个对象 GET 与 GET return 集合执行 return 不同的数据,它不会 RESTful 吗?
是的,我会将过滤器参数作为查询字符串选项传递。您的应用程序 'restfulness' 不依赖于控制器结构,因此您可以遵循最适合您的应用程序的结构
For the first URL above, I need to also send various filter/search criteria. Does this criteria just get passed through as query string parameters?
使用查询字符串指定 filter/search 参数绝对有意义。
should I be using a completely different controller for this "search" functionality? Eg. UserSearchController?
你不应该那样做。我在这里看到有几个原因:
GET: /api/users
中的功能几乎相同
您可以通过一种方法轻松实现 GET: /api/users
、GET: /api/users?filter=...&sort=...
和 GET: /api/users/1
:
//If you are using EF it could look like
//filter and sort arguments could be added here as well
public HttpResponseMessage Get(int? id)
{
if(id.HasValue)
{
return Request.CreateResponse(
HttpStatusCode.OK,
Context.Users.SingleOrDefault<Users>(u => u.Id == id));
}
var users = Context.Users.Select(apply filter).OrderBy(apply sort).ToList();
return Request.CreateResponse(HttpStatusCode.OK, users);
}
您可以看一下 OData - 它可能对您的实施有所帮助。
- 在不同的控制器之间传播这个逻辑会损害单一责任原则 - 你的用户控制器应该处理与用户相关的所有逻辑并且只处理这个逻辑
If so, should that be a POST in this case or still a GET?
如果你想让你的 API RESTful 你应该使用 GET。 但是 你应该知道,通过 GET returning 一个 JSON 对象数组可能容易受到 JSON hijacking 的攻击。针对此漏洞利用的最简单解决方案之一是仅允许通过 POST 获取 JSON 数组(还有其他解决方案)。
I'll probably want more detail returned in the GET for a single user than in the search results. Does it make it not RESTful if the same controller does return different data for a single object GET vs a GET returning a collection?
这对于 return 单个对象的详细信息比集合的详细信息完全没问题。它不会以任何方式影响您 API 的 RESTfulness。
评论
您写道:
PUT for update when specifying an ID
其实并不完全正确:
- PUT 应该用于完全替换整个实体
- 应该使用 PATCH 来执行部分更新。
如果你想通过标准作为查询字符串参数传递给 URI,你可以使用属性路由到 WebApi 来实现。我觉得 attribute-routing-in-web-api 对你有帮助。
我正在使用 WebAPI 编写 API,虽然我是从头开始设计它,但我正在努力实现它 RESTful。过去在做 Web 服务工作时,我总是使用 RPC 模式(ASMX、SOAP 等)——例如。使用与我想要它做的相匹配的任意方法名称。对我来说,这似乎比 REST 更直观和明确,但考虑到 WebApi 似乎更 RESTful 本质上(我知道你可以改变路线,所以它不是),我决定尝试制作它 RESTful.
我了解(我认为!)基础知识 - 例如。 POST创建,指定ID时PUT更新,GET获取,DELETE删除等
我的困惑是如何处理 returning 集合与单个对象。例如,假设我有一个名为 UsersController
的 API 控制器。据我所知,我有以下 URLs:
GET: /api/users (lists all users)
GET: /api/users/1 (lists details about user with ID 1)
POST: /api/users (creates a new user with details sent in the POST data)
PUT: /api/users/1 (updates the existing user with ID 1 with details sent in the POST data)
DELETE: /api/users/1 (deletes the existing user with ID 1)
对于上面的第一个 URL,我还需要发送各种 filter/search 条件。这个条件是否只是作为查询字符串参数传递?或者我应该为这个 "search" 功能使用完全不同的控制器吗?例如。用户搜索控制器?如果是这样,在这种情况下应该是 POST 还是 GET?事实上,在我写这篇文章时,我想知道一个单独的控制器是否有意义,因为我可能希望在 GET 中为单个用户提供比搜索结果更多的详细信息 return。如果同一个控制器对单个对象 GET 与 GET return 集合执行 return 不同的数据,它不会 RESTful 吗?
是的,我会将过滤器参数作为查询字符串选项传递。您的应用程序 'restfulness' 不依赖于控制器结构,因此您可以遵循最适合您的应用程序的结构
For the first URL above, I need to also send various filter/search criteria. Does this criteria just get passed through as query string parameters?
使用查询字符串指定 filter/search 参数绝对有意义。
should I be using a completely different controller for this "search" functionality? Eg. UserSearchController?
你不应该那样做。我在这里看到有几个原因:
GET: /api/users
中的功能几乎相同
您可以通过一种方法轻松实现
GET: /api/users
、GET: /api/users?filter=...&sort=...
和GET: /api/users/1
://If you are using EF it could look like //filter and sort arguments could be added here as well public HttpResponseMessage Get(int? id) { if(id.HasValue) { return Request.CreateResponse( HttpStatusCode.OK, Context.Users.SingleOrDefault<Users>(u => u.Id == id)); } var users = Context.Users.Select(apply filter).OrderBy(apply sort).ToList(); return Request.CreateResponse(HttpStatusCode.OK, users); }
您可以看一下 OData - 它可能对您的实施有所帮助。
- 在不同的控制器之间传播这个逻辑会损害单一责任原则 - 你的用户控制器应该处理与用户相关的所有逻辑并且只处理这个逻辑
If so, should that be a POST in this case or still a GET?
如果你想让你的 API RESTful 你应该使用 GET。 但是 你应该知道,通过 GET returning 一个 JSON 对象数组可能容易受到 JSON hijacking 的攻击。针对此漏洞利用的最简单解决方案之一是仅允许通过 POST 获取 JSON 数组(还有其他解决方案)。
I'll probably want more detail returned in the GET for a single user than in the search results. Does it make it not RESTful if the same controller does return different data for a single object GET vs a GET returning a collection?
这对于 return 单个对象的详细信息比集合的详细信息完全没问题。它不会以任何方式影响您 API 的 RESTfulness。
评论
您写道:
PUT for update when specifying an ID
其实并不完全正确:
- PUT 应该用于完全替换整个实体
- 应该使用 PATCH 来执行部分更新。
如果你想通过标准作为查询字符串参数传递给 URI,你可以使用属性路由到 WebApi 来实现。我觉得 attribute-routing-in-web-api 对你有帮助。