【问题标题】:Simple way to UPDATE an item using ASP .Net Core API controller and POSTMAN使用 ASP .Net Core API 控制器和 POSTMAN 更新项目的简单方法
【发布时间】:2019-04-18 12:00:14
【问题描述】:

通过这种使用 PUT 动词的简单方法来使用 ASP.Net Core 2.2 和 Postman 更新项目,我创建了如下模型:

public class Product
{
    public Guid Id { get; set; }

    public string Name { get; set; }    
}

一个控制器方法如下:

// PUT: api/PutProduct/5
[HttpPut("api/[action]/{id}")]
public async Task<IActionResult> PutProduct(Guid id, Product Product)
{
    if (id != Product.Id)
    {
        return BadRequest();
    }

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

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

    // return NoContent();
    return AcceptedAtAction("GetProduct", new { id = Product.Id, name = Product.Name }, Product);
}

然后是一个JSON体如下:

{
    "name": "Product (Edited)"
}

现在,当我单击 Postman PUT 方法时,它会返回 202 状态,但不会使用新值更新“名称”字段,而是将其清除。

如果我添加 [FromBody] 如下,它返回 400 错误(错误请求):

public async Task<IActionResult> PutProduct(Guid id, [FromBody] Product Product)

我在这里做错了什么?

【问题讨论】:

  • 你的控制器是用[ApiController]装饰的吗?如果我没看错,400 是预期的响应,因为您没有在邮递员请求中传递 id。
  • @k3davis 我在 url 中传递了一个 id,我不需要 [ApiController] 装饰,因为我在方法路由中指定了它。

标签: c# asp.net-core postman http-put


【解决方案1】:

在第一个示例中,id 从路由中填充模型的 id,而不是名称。这就是为什么它通过了错误的请求检查并且名称将被清除,因为它没有被填充。

在第二个示例中,您发送的正文不包含未通过验证检查的 id

如果在这种情况下使用[FromBody],则需要在 JSON 有效负载中包含 id。

{
    "id": "{Guid_here}",
    "name": "Product (Edited)"
}

否则你需要重新考虑动作的设计/流程

您应该考虑使用ModelState.IsValid 检查数据的模型状态以确保其有效。

使用数据注释的第一个更新模型

public class Product {
    [Required]
    public Guid Id { get; set; }
    [Required]
    public string Name { get; set; }    
}

并检查动作中的状态。

[HttpPut("api/[action]/{id}")]
public async Task<IActionResult> PutProduct(Guid id, [FromBody]Product Product) {

    if (id != Product.Id) {
        ModelState.AddModelError("Id", "Invalid Id");
    }

    if(!ModelState.IsValid) {
        return BadRequest(ModelState);
    }

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

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

    return AcceptedAtAction("GetProduct", new { id = Product.Id, name = Product.Name }, Product);
}

此外,您可以使用有关从何处绑定数据的注释来更新模型。

例如

public class Product {
    [Required]
    [FromRoute] //<--
    public Guid Id { get; set; }
    [Required]
    public string Name { get; set; }    
}

注意添加的属性。

并发送原始有效载荷

{
    "name": "Product (Edited)"
}

参考Model Binding in ASP.NET Core

【讨论】:

  • 你说得对,因为我专注于使用 [FromBody] 的第一种方法,并且省略了在 JSON 有效负载中添加“id”,所以我现在已经尝试过了,它可以工作。您知道如何在使用路由中的 id 时更新名称吗?
  • @Sami-L 包含一些选项。
  • 如果我在模型中使用 [FromRoute("id")] 它会说:FromRouteAttribute 不包含带 1 个参数的构造函数。
  • @Sami-L 等等,让我重新检查一下
  • @Sami-L 可以删除它。我在考虑以前的版本。
猜你喜欢
  • 2017-07-15
  • 1970-01-01
  • 2020-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 2019-03-10
  • 2017-01-26
相关资源
最近更新 更多