首页 > 解决方案 > 在带有 Entity Framework Core 的 ASP.NET Core WebAPI 的这个 PUT 方法中检查的目的是什么?

问题描述

我有一个带有 Entity Framework Core 的 ASP.NET Core WebAPI 应用程序。

我有以下模型类:

public class Item
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    [Required(ErrorMessage = "You must provide a name.")]
    [MaxLength(255)]
    public string Name { get; set; }
}

并搭建了一个“带有动作的API控制器,使用实体框架”,它具有以下方法:

    [HttpPut("{id}")]
    public async Task<IActionResult> PutItem(long id, Item item)
    {
        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();
    }

我不明白if (id != item.Id)支票。该Id属性设置为是DatabaseGenerated因为我希望它是我的主键,自动递增而不是由客户端提供,因此客户端可以只放置一个{"name":"item1"}对象并成功。

那么为什么会有这个检查呢?是自动代码生成器的故障吗?我可以安全地删除它吗?

此外,如果 ID 不是数据库生成的,此检查是否可以确保用户传递的对象与他尝试更新的 ID 具有相同的 ID?

标签: c#asp.net-coreasp.net-web-apientity-framework-core

解决方案


id值来自 URL 路由:

[HttpPut("{id}")]

item.Id价值来自发布的模型。人们可能认为两者兼有是多余的,但前者是标准 RESTful API 的一部分,而后者可能只是为了请求正文中模型的完整性。

这里的意图只是一个防御性编程检查,以确保两者相同。如果有人提交了两个不同的值,那么从语义上讲,它看起来像是试图修改记录的 ID,这当然不应该被允许。这只是针对此的健全性检查。

并且不是由客户提供

客户必须提供两者之一,以便您识别要更新的记录。如果需要,您通常可以忽略,item.Id而只使用idURL 路由中的值来识别记录。 但是,如果你这样做,那么你还需要做以下两件事之一:

  1. item.Id = id;在尝试将其附加到数据库上下文之前添加一行代码进行设置,或者
  2. 与其将模型直接添加到数据库上下文中,不如将其id作为单独的对象获取记录并手动更新要更新的字段。

毕竟,如果item.Id不是由客户端提供,那么它将默认为0Entity Framework 将无法在没有Id值的情况下直接附加该对象。上述选项将通过直接在对象上设置或在重新获取的对象上使用现有值来提供该值。


推荐阅读