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<T>(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 IIS 在选项请求上返回 502