ASP.net Core RC2 Web API POST - 何时使用 Create、CreatedAtAction 和 CreatedAtRoute?

Posted

技术标签:

【中文标题】ASP.net Core RC2 Web API POST - 何时使用 Create、CreatedAtAction 和 CreatedAtRoute?【英文标题】:ASP.net Core RC2 Web API POST - When to use Create, CreatedAtAction, vs. CreatedAtRoute? 【发布时间】:2016-10-16 19:05:26 【问题描述】:

这些功能的根本区别是什么?我只知道这三个结果都是 201,这适用于成功的 POST 请求。

我只关注我在网上看到的示例,但他们并没有真正解释他们为什么要做他们正在做的事情。

我们应该为我们的 GET 提供一个名称(1 条记录按 id):

[HttpGet("id", Name="MyStuff")]
public async Task<IActionResult> GetAsync(int id)

     return new ObjectResult(new MyStuff(id));

命名这个get函数的目的是什么,除了它“可能”是下面的POST函数所必需的:

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)

     // actual insertion code left out

     return CreatedAtRoute("MyStuff", new  id = myStuff.Id , myStuff);

我注意到CreatedAtRoute 也有一个不包含路由名称的重载。

还有CreatedAtAction 接受类似的参数。为什么会存在这种变体?

还有Created 需要一个URL 和我们想要返回的对象。我可以只使用这个变体并提供一个虚假的 URL 并返回我想要的对象并完成它吗?

我不确定为什么有这么多变体只是为了能够向客户端返回 201。在大多数情况下,我想要做的就是返回“应用程序分配”(很可能来自数据库)唯一 id 或我的实体的具有最少信息的版本。

我认为最终,一个 201 响应“应该”创建一个包含新创建资源的 URL 的位置标头,我相信所有 3 个及其重载最终都会这样做。为什么我应该总是返回一个位置标头?我的 javascript 客户端、原生移动和桌面应用程序从不使用它。例如,如果我发出 HTTP POST 来创建账单并将其发送给用户,那么这样的位置 URL 会是什么? (我很抱歉没有深入挖掘互联网的历史来寻找答案。)

为什么要为动作和路由命名?动作名和路由名有什么区别?

我对此感到困惑,所以我求助于返回 Ok(),它返回 200,这不适合 POST。

【问题讨论】:

【参考方案1】:

这里有几个不同的问题可能应该分开,但我认为这涵盖了您的大部分问题。

为什么要为动作和路由命名?动作名和路由名有什么区别?

首先,动作和路线是非常不同的。

动作存在于控制器上。路由指定了一个完整的端点,该端点由控制器、操作和可能的其他其他路由参数组成。

您可以为路由命名,这样您就可以在应用程序中引用它。例如

routes.MapRoute(
  name: "MyRouteName",
  url: "SomePrefix/action/id",
  defaults: new  controller = "Section", action = "Index" 
);

动作名称的原因包含在这个问题中:Purpose of ActionName

它允许您以数字开始您的操作或在标识符中包含 .net 不允许的任何字符。 - 最常见的原因是它允许您有两个具有相同签名的操作(请参阅任何脚手架控制器的 GET/POST 删除操作)

这些功能的根本区别是什么?

这 3 个函数基本上都执行相同的功能 - 返回一个 201 Created 响应,带有一个指向新创建响应的 url 的 Location 标头,以及主体中的对象本身。 url 应该是 GET 请求返回对象 url 的 url。这将被视为 RESTful 系统中的“正确”行为。

对于您问题中的示例邮政编码,您实际上希望使用CreatedAtAction

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
  
   // actual insertion code left out

   return CreatedAtAction("MyStuff", new  id = myStuff.Id , myStuff);

假设您配置了默认路由,这将添加一个 Location 标头,指向同一控制器上的 MyStuff 操作。

如果您希望位置 url 指向特定路线(如我们之前定义的,您可以使用例如

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
  
   // actual insertion code left out

   return CreatedAtRoute("MyRouteName", new  id = myStuff.Id , myStuff);

我可以只使用这个变体并提供一个虚假的 URL 并返回我想要的对象并完成它吗?

如果你真的不想使用CreatedResult,你可以使用一个简单的StatusCodeResult,它会返回一个201,没有Location Header 或body。

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
  
  // actual insertion code left out

  return StatusCode(201);

【讨论】:

我不确定 .NET Core,但 Content&lt;T&gt;(HttpStatusCode, T content) 方法是否仍然存在以返回状态代码和内容?这应该允许返回 201 以及新创建的对象,而不包括 Location 标头。 该重载似乎不再存在,但实际上有一个 StatusCode 重载,您可以类似地使用:StatusCode(int httpStatusCode, object value) 似乎[HttpGet("id", Name = "GetUser",Order = 0)] 创建路由的方式似乎不适用于 CreatedAtRoute() 带有一个 Location 标头,指向新创建的响应的 URL,以及主体中的对象本身。我很抱歉,但我无法理解这一点。请你解释清楚好吗?【参考方案2】:

最新文档https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-3.1 中提到,这一切都非常令人困惑

看起来“他们”不希望在即将到来的时代发展成为一个简单的过程......

【讨论】:

以上是关于ASP.net Core RC2 Web API POST - 何时使用 Create、CreatedAtAction 和 CreatedAtRoute?的主要内容,如果未能解决你的问题,请参考以下文章

在 asp.net core rc2 中指定代理

ASP.NET Core RC2 IIS 在选项请求上返回 502

开源Asp.Net Core小型社区系统

ASP.NET Core RC2 中的依赖注入失败

ASP.NET Core RC2 Jwt 令牌 KID 错误

如何在 ASP.NET core rc2 中禁用浏览器缓存?