【问题标题】:"True" REST routing via MVC 4 Web API通过 MVC 4 Web API 的“真”REST 路由
【发布时间】:2012-12-14 14:19:42
【问题描述】:

TL;DR 摘要:我可以为 HTTP GET、PUT 和 DELETE 配置 MVC Web API 路由吗?

我一直在考虑用私有 API 替换我们旧的数据访问层(基于 DataSet 和 TableAdapters 的 DLL),以期在成功后创建公共 API。我已经使用 MVC 4 完成了一些工作来更新我们的前端,并且喜欢使用它,因此在深入研究基于 WS 或 WCF 的库之前探索“Web API”项目类型似乎是明智的。

初始演示允许我很好地返回 XML/JSON,例如:

//service.url/api/Users

...返回用户列表,而特定用户的详细信息可以通过以下方式访问:

//service.url/api/Users/99

到目前为止,还是 RESTful 的。但是,为了真正将 URI 映射到资源,我想对上面列出的 URI 执行 HTTP PUT(新用户)或 HTTP DELETE(删除用户)。在我为这些项目看到的所有示例中,以及 Visual Studio 中提供的 Scaffolds 中,都遵循以下约定:

//service.url/api/Users/Create

//service.url/api/Users/Delete/99

//service.url/api/Users/Update/99

... 等等。这对我来说就像是在回避这个问题,当那里的东西如此完美地组合在一起时,这是一种耻辱!

关于如何最好地解决这个问题有什么想法吗?

【问题讨论】:

  • 您要查找的实际上是 Web API 中的默认路由。您遇到了什么问题?

标签: c# asp.net api rest asp.net-routing


【解决方案1】:

你想要的是 MVC Web API 中的默认值。我不确定你在看什么,但这里是 routing the Get/Post/Put/Delete to actions 的一个很好的例子。

例如你可能想要:

public class UsersController : ApiController
{
  // GET http://service.url/api/Users/1
  [HttpGet]
  public User GetUser(int id);

  // POST http://service.url/api/Users/?name=richard...
  [HttpPost]
  public User AddUser(User model);      

  // PUT http://service.url/api/Users/?id=1&name=Richard...
  [HttpPut]
  public User UpdateUser(User model);

  // DELETE http://service.url/api/Users/1
  [HttpDelete]
  public User DeleteUser(int id);
}

我已经明确设置了这些,但 GetUserDeleteUser 不需要前缀,因为它们是 start with the matching HTTP method

【讨论】:

  • 谢谢,太棒了!我不知道命名约定是如此精细。
【解决方案2】:

Erik 提供的链接是一个好的开始,但是当我寻找一个使用 HTTP 动词来执行这些 CRUD 操作的简单 RESTful API 时,我发现它会如何混淆情况。如果您正在寻找使用 GET、PUT、POST 和 DELETE 的 HTTP 动词(可能还有 PATCH,但我在这里不涉及)并且您可以使用约定,那么以下方法将起作用:

public class UsersController : ApiController
{
    // GET http://service.url/api/Users
    public User GetAllUsers(){ ... }

    // GET http://service.url/api/Users/1
    public User GetUser(int id){ ... }

    // POST http://service.url/api/Users/
    // User model is passed in body of HTTP Request
    public User PostUser([FromBody]User model){ ... }

    // PUT http://service.url/api/Users/1
    // User model is passed in body of HTTP Request
    public User PutUser(int id, [FromBody]User model){ ... }

    // DELETE http://service.url/api/Users/1
    public User DeleteUser(int id){ ... }
}

请注意,在 Web API 中使用 HTTP 动词操作约定时,不需要方法上的属性。另外,请注意,我在 POST 和 PUT 的 User 参数上使用 [FromBody] 属性来表示正文包含我希望发送的数据。如果您尝试附加到资源,这对于 POST 可能不是最方便的,而且我还没有尝试使用 Web API 通过查询参数创建/修改数据。将您的数据放在正文中肯定会让通话感觉非常干净。 “在此资源的正文中发布/放置此内容。”

此外,我在规范中阅读 PUT 的方式很可能是错误的,因为它充当了替代品。鉴于上面的最后一行,这也是有道理的。我将这个资源放在这个位置,替换已经存在的资源。规范 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) 声明:“如果 Request-URI 引用了一个已经存在的资源,则封闭的实体应该被视为驻留在源服务器上的实体的修改版本。”他们使用的术语是“修改过的”,所以我想这为最终用户留下了足够的解释空间。这就是 PATCH 的用武之地 (https://www.rfc-editor.org/rfc/rfc5789),但我目前没有足够的信息对此发表评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 2012-09-28
    • 2012-09-26
    • 1970-01-01
    • 2011-11-05
    • 2012-07-09
    • 1970-01-01
    相关资源
    最近更新 更多