我正在尝试使用 ASP.NET Web API 为我们的服务设计一个 RESTful Web API。我在弄清楚如何将非 CRUD 操作路由到正确的控制器操作时遇到了麻烦。假设我的资源是一扇门。我可以用我的门做所有熟悉的 CRUD 事情。假设我的门的模型是:
public class Door
{
public long Id { get; set; }
public string InsideRoomName { get; set; }
public string OutsideRoomName { get; set; }
}
我可以通过我的 web api 完成所有标准的 CRUD 操作:
POST: http://api.contoso.com/v1/doors
GET: http://api.contoso.com/v1/doors
GET: http://api.contoso.com/v1/doors/1234
GET: http://api.contoso.com/v1/doors?InsideRoomName=Cafeteria
PUT: http://api.contoso.com/v1/doors/1234
DELETE: http://api.contoso.com/v1/doors/1234
等等。我遇到麻烦的地方是当我需要对我的门进行非 CRUD 操作建模时。我想对我的资源建模一个 Lock 和 Unlock 动词。阅读ASP.NET 文章,该指南似乎是在使用自定义操作时切换到 RPC 样式调用。这给了我一条路径:
PUT: http://api.contoso.com/v1/doors/1234/lock
PUT: http://api.contoso.com/v1/doors/1234/unlock
这似乎与旨在指示资源的路径的 REST 精神相冲突。我想我可以将动词建模为资源:
POST: http://api.contoso.com/v1/doors/1234/lockrequests
POST: http://api.contoso.com/v1/doors/1234/unlockrequests
在这种情况下,我仍然可以使用推荐的 {controller}/{id}/{action} 但似乎我仍在创建混合 RPC / REST API。就 REST 接口而言,是否有可能,甚至推荐将自定义操作放在参数列表中?
PUT: http://api.contoso.com/v1/doors/1234?lock
PUT: http://api.contoso.com/v1/doors/1234?unlock
我可以预见需要使用查询参数支持此调用,例如:
PUT: http://api.contoso.com/v1/doors?lock&InsideRoomName=Cafeteria
我将如何创建将这个请求映射到我的 DoorsController 的路由?
public class DoorsController : ApiController
{
public IEnumerable<Doord> Get();
public Door Get(long id);
public void Put(long id, Door door);
public void Post(Door door);
public void Delete(long id);
public void Lock(long id);
public void Unlock(long id);
public void Lock(string InsideRoomName);
}
关于 REST API 设计方面什么是最佳实践,什么不是最佳实践,我可能在这里做出了一些错误的假设,因此也欢迎任何指导。