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

Mic*_*uso 42 http-post asp.net-web-api asp.net-core-mvc asp.net-core

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

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

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

[HttpGet("{id}", Name="MyStuff")]
public async Task<IActionResult> GetAsync(int id)
{
     return new ObjectResult(new MyStuff(id));
}
Run Code Online (Sandbox Code Playgroud)

命名此get函数的目的是什么,除了它可能是以下POST函数所需的"可能":

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

     return CreatedAtRoute("MyStuff", new { id = myStuff.Id }, myStuff);
}
Run Code Online (Sandbox Code Playgroud)

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

还有一个CreatedAtAction类似的参数.为什么存在这种变体?

还有Created一个期望URL和我们想要返回的对象.我可以使用这个变体并提供一个伪造的URL并返回我想要的对象并完成它并完成吗?

我不确定为什么有这么多的变种只是为了能够将201返回给客户端.在大多数情况下,我想要做的就是返回"app-assigned"(很可能来自数据库)唯一ID或具有最少信息的我的实体版本.

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

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

我对此感到困惑,所以我使用了Ok()返回200,这不适合POST.

Soc*_*ock 42

这里有一些不同的问题可能会分开,但我认为这涵盖了你的大部分问题.

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

首先,行动和路线是非常不同的.

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

您可以为路径指定名称,以便在应用程序中引用它.例如

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

此问题涵盖了操作名称的原因:ActionName的用途

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

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

这3个函数都执行基本相同的函数 - 返回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);
}
Run Code Online (Sandbox Code Playgroud)

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

如果您希望位置URL指向特定路径(如前所述,您可以使用例如

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

   return CreatedAtRoute("MyRouteName", new { id = myStuff.Id }, myStuff);
}
Run Code Online (Sandbox Code Playgroud)

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

如果你真的不想使用a CreatedResult,你可以使用一个简单的StatusCodeResult,它将返回一个201,没有LocationHeader或body.

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

  return StatusCode(201);
}
Run Code Online (Sandbox Code Playgroud)

  • 那个重载似乎不再存在,但实际上有一个 StatusCode 的重载,您可以类似地使用它:`StatusCode(int httpStatusCode, object value)` (2认同)
  • 似乎`[HttpGet("{id}",Name ="GetUser",Order = 0)]`创建路径的方式似乎不适用于CreatedAtRoute() (2认同)