【问题标题】:What is the correct status code to return for a successful PUT operation performed by a RESTful API?RESTful API 执行的成功 PUT 操作返回的正确状态代码是什么?
【发布时间】:2019-02-11 15:14:51
【问题描述】:

在 Visual Studio 2017 中,为 .Net Core 2.1 Web API 创建新控制器并使用“使用实体框架添加脚手架 - 带有操作的 API 控制器”向导时,生成的控制器代码为 PUT 操作返回一个 NoContent(),为 POST 操作返回一个 CreatedAtAction()

    // POST: api/Items
    [HttpPost]
    public async Task<IActionResult> PostItem([FromBody] Item item)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        _context.Item.Add(item);
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetItem", new { id = item.Id }, item);
    }

    // PUT: api/Items/5
    [HttpPut("{id}")]
    public async Task<IActionResult> PutItem([FromRoute] int id, [FromBody] Item item)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        if (id != item.Id)
            return BadRequest();

        _context.Entry(item).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!ItemExists(id))
                return NotFound();
            else
                throw;
        }

        return NoContent();
    }

我完全同意 POST 操作的返回值。但是关于 PUT 操作返回一个空主体的 NoContent(),这是 RESTful API 的“最佳实践”吗?我的意思是,我知道它返回 NoContent() 状态代码是因为正文为空,但如果它返回 Ok() 表示一切正常,岂不是更有意义?在接收到 NoContent() 状态代码时,操作是否成功似乎有点模棱两可。还是返回 NoContent() 更正确,让消费应用知道它应该忽略正文,并假​​设因为没有返回错误代码,所以一切正常?

只是想知道 RESTful 最佳实践在这种情况下的规定...

【问题讨论】:

  • 没有内容仍然落在 2xx 状态码范围内,这都表明请求处理成功。 restapitutorial.com/httpstatuscodes.html。返回 200 现在只是一个选择问题
  • HTTP 200 表示成功请求。
  • 我想问同样的问题,但我的主要问题不是返回NoContent 而不是Ok,而是为什么返回一个空的正文而不是具有更新资源的正文
  • 你提到 Veverke 很有趣,我最近只是想知道完全相同的事情。我猜在 PUT 操作中,由于 API 消费者告诉 API 应该更新什么,将这些信息发送回消费者是多余的吗?而使用 POST 操作,将生成一个新的 ID,消费者需要知道它,因此在正文中返回新创建的对象。我实际上目前正在使用一个 API,它在对 PUT 操作的响应主体中返回一个对象。就像 Nkosi 评论的那样,它是可选的 - 如果你愿意,你可以返回对象,但它会消耗更多的带宽。

标签: rest asp.net-core-webapi asp.net-core-2.1


【解决方案1】:

返回无内容状态仍然在 2xx 状态码范围内,这都表示请求处理成功。在这种情况下,返回 200 现在只是一个选择问题,而不是最佳实践规定

参考Learn REST: A RESTful Tutorial - Using HTTP Methods for RESTful Services

PUT 最常用于更新功能,PUT 请求正文包含新更新的已知资源 URI 原始资源的表示。

但是,PUT 也可用于在以下情况下创建资源 资源 ID 由客户端而不是服务器选择。在 换句话说,如果 PUT 指向一个包含 a 值的 URI 不存在的资源 ID。同样,请求正文包含一个资源 表示。许多人认为这是令人费解和令人困惑的。 因此,应谨慎使用这种创建方法,如果在 全部。

或者,使用 POST 创建新资源并提供 主体表示中客户端定义的 ID——可能是一个 URI 不包括资源的 ID(参见下面的 POST)。

成功更新时,返回 200(如果不返回任何内容,则返回 204 在体内)来自 PUT。如果使用 PUT 创建,则返回 HTTP 状态 201关于成功创建。响应中的主体是 可选——提供一个消耗更多带宽。没有必要 在创建案例中通过 Location 标头返回链接,因为 客户端已设置资源 ID。

PUT 不是安全操作,因为它会修改(或创建)状态 服务器,但它是幂等的。换句话说,如果您创建或 使用 PUT 更新资源,然后再次进行相同的调用, 资源仍然存在并且仍然具有与它相同的状态 第一次通话。

例如,如果对资源调用 PUT 会增加计数器 在资源内,调用不再是幂等的。有时那 发生并且可能足以证明呼叫不是 幂等的。但是,建议保持 PUT 请求是幂等的。 强烈建议对非幂等请求使用 POST。

【讨论】:

  • 正如我在问题的 cmets 中指出的那样,我的问题是,如果您可以返回更新的资源,为什么返回 NoContent 时的正文为空。听起来更直观。对此有何评论?
  • 好吧,我突然想到,实际上根本没有理由返回更新的资源 - 因为更新的源是由发送者发送的,发送者在获取它本身发送的源时没有任何好处用于更新...
猜你喜欢
  • 2019-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-15
  • 2019-02-16
  • 2023-01-11
  • 1970-01-01
  • 2021-07-27
相关资源
最近更新 更多