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

时间:2016-06-15 15:09:13

标签: asp.net-web-api http-post asp.net-core asp.net-core-mvc

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

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

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

[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返回给客户端。在大多数情况下,我想要做的就是返回“app-assigned”(最有可能来自数据库)唯一ID或我的实体版本信息最少。

我认为最终,201响应“应该”创建一个位置标题,其中包含新创建的资源的URL,我相信所有3和它们的重载最终会完成。为什么我总是要返回一个位置标题?我的JavaScript客户端,本机移动和桌面应用程序从不使用它。例如,如果我发出HTTP POST来创建账单并将其发送给用户,这样的位置URL会是什么? (我很抱歉没有深入了解互联网的历史,为此寻找答案。)

为什么要为动作和路线创建名称?动作名称和路线名称之间有什么区别?

我对此感到困惑,所以我试图返回Ok(),返回200,这不适合POST。

1 个答案:

答案 0 :(得分:36)

这里有一些不同的问题应该分开,但我认为这涵盖了你的大部分问题。

为什么要为动作和路线创建名称?行动名称和路线名称之间有什么区别?

首先,行动和路线非常不同。

动作生活在控制器上。路由指定一个完整的端点,由Controller和Action以及其他可能的其他路由参数组成。

您可以为路线命名,以便您在应用程序中引用它。例如

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

此问题涵盖了操作名称的原因:Purpose of ActionName

  

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

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

这三个函数都执行基本相同的函数 - 返回201 Created响应,Location标题指向新创建的响应的url,以及对象本身在正文中。 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);
}

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

如果您希望位置网址指向特定路线(如前所述,您可以使用例如。

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

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

我可以使用此变体并提供虚假网址并返回我想要的对象并完成并完成吗?

如果您确实不想使用CreatedResult,则可以使用简单的StatusCodeResult,它将返回201,而不包含Location标题或正文。

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

  return StatusCode(201);
}