简体   繁体   中英

What is the purpose of this check in this PUT method of ASP.NET Core WebAPI with Entity Framework Core?

I have an ASP.NET Core WebAPI application with Entity Framework Core.

I have the following model class:

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; }
}

and scaffolded an "API Controller with actions, using Entity Framework", which has the following method:

    [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();
    }

I don't understand the if (id.= item.Id) check. The Id property is set to be DatabaseGenerated because I want it to be my primary key, autoincrementing and NOT provided by the client, so the client can just PUT a {"name":"item1"} object and be successful.

So why is there this check? Is it a fault of the auto code generator? Can I safely remove it?

Furthermore, if the ID wasn't database generated, is this check to ensure that the user passes an object that has the same ID as the one he is trying to update?

The id value is coming from the URL route:

[HttpPut("{id}")]

And the item.Id value is coming from the posted model. One may consider it redundant to have both, but the former is part of a standard RESTful API and the latter is likely just for completeness of the model in the request body.

The intent here is just a defensive programming check to make sure both are the same. If someone submitted two different values then semantically it would look like an attempt to modify the ID of a record, which should certainly not be allowed. This is just a sanity check against that.

and NOT provided by the client

The client would have to provide one of the two in order for you to identify the record to update. You can generally ignore the item.Id if you want and just use the id value from the URL route to identify the record. However , if you do that then you'd need to also do one of two things:

  1. Add a line of code to set item.Id = id; before trying to attach it to the DB context, or
  2. Instead of adding the model directly to the DB context, fetch the record by its id as a separate object and manually update the fields you want to update.

After all, if item.Id isn't provided by the client then it's going to default to 0 and Entity Framework won't be able to attach that object directly without an Id value. The above options would supply that value either by setting it directly on the object or by using the existing one on a re-fetched object.

POST is typically used to create an object. PUT is often for an update. And to update it, you need to know its identity. Most likely long id is part of the URL or query string. And Item item is from the body. That check ensures the entity supplied in the body matches the one specified by the URL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM