如何在一个RESTful的ASP.NET Web API路线非CRUD操作?(How to Rout

2019-08-31 12:30发布

我试图设计使用的ASP.NET Web API我们的服务REST风格的Web API。 我遇到麻烦,首先要弄清楚非CRUD如何路由行动,以适当的控制器动作。 假设我的资源是一扇门。 我可以做所有的熟悉CRUD的东西与我的门。 假设模型我的门是:

public class Door
{
   public long Id { get; set; }
   public string InsideRoomName { get; set; }
   public string OutsideRoomName { get; set; }
}

我可以通过我的网络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操作模型。 我想建模锁定和解锁动词对我的资源。 通过阅读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

在这种情况下,我仍然可以使用建议{控制器} / {ID} / {行动},但它好像我还是创建一个混合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设计不是最佳做法,所以任何指导有赞赏也。

Answer 1:

为了处理lock/unlock情况下,您可以考虑增加一个State属性的Door对象:

   public State State { get; set; }

其中,国家可用的价值观,例如枚举

{
LockedFromOutsideRoom,
LockedFromInsideRoom,
Open
}

为了澄清:您要添加一个状态到对象的状态在API每次拨打电话做一些同门时间的推移,不反对宁静的原则。

然后,通过API,你会发送一个PUT/POST请求更改每个锁定/解锁车门的状态。 帖子可能会更好,因为它是唯一一个获得更新的属性:

POST: http://api.contoso.com/v1/doors/1234/state
body: {"State":"LockedFromInsideRoom"}


Answer 2:

从RESTful的原则,也许这是最好引入“状态”属性来管理这些非CURD操作。 但我不认为它符合实际生产的发展。

每回答这样的问题,看起来你必须使用一个变通执行你的API设计符合REST风格。 但我担心的是,真的是让方便用户和开发者?

让我们在谷歌bloger的API3.0设计一看: https://developers.google.com/blogger/docs/3.0/reference ,它使用大量的URL非CURD操作。

这是有趣的,

POST  /blogs/blogId/posts/postId/comments/commentId/spam

和描述是

标记为垃圾评论。 这将设置为垃圾留言的状态,并把它藏在默认注释渲染。

你可以看到,评论有一个状态,表明它是否是垃圾邮件或不是,但它并没有像设计通过JoannaTurban上述问题的答案。

我想,但从用户角度来说,它更方便。 不要需要关心的结构和“状态”的枚举值。 而实际上你可以把大量的属性进入“状态”的定义,如“isItSpam”,“isItReplied”,“isItPublic”等。如果状态有很多事情都会变得不友善的设计。

在一些业务逻辑的要求,用一种易于理解动词,而不是试图使之完全一个“真正的” REST风格,它更高效,既为用户和开发人员。 这是我的意见。



Answer 3:

从静止的角度,你可能要被处理锁在本身的资源。 这样,您创建和删除独立门的锁(尽管可能从门表示定位​​锁终点)。 资源的URL很可能将涉及到门的URL,但是从REST风格的角度来看,这是无关紧要的。 REST是关于资源之间的关系,所以重要的是,锁的网址是从门的代表发现。



文章来源: How to Route non-CRUD actions in a RESTful ASP.NET Web API?