Какова цель этой проверки в этом методе PUT ASP. NET Core WebAPI с Entity Framework Core? - PullRequest
0 голосов
/ 28 мая 2020

У меня есть приложение ASP. NET Core WebAPI с Entity Framework Core.

У меня есть следующий класс модели:

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 с действия с использованием Entity Framework ", который имеет следующий метод:

    [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"} и добиться успеха.

Так почему там эта проверка? Это ошибка автогенератора кода? Могу ли я безопасно удалить его?

Более того, если идентификатор не был сгенерирован в базе данных, должна ли эта проверка гарантировать, что пользователь передает объект с тем же идентификатором, что и тот, который он пытается обновить?

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Значение id поступает из маршрута URL:

[HttpPut("{id}")]

А значение item.Id поступает из опубликованной модели. Можно считать избыточным наличие обоих, но первый является частью стандартного RESTful API, а второй, скорее всего, предназначен только для полноты модели в теле запроса.

Цель здесь - просто защитная проверка программирования чтобы убедиться, что оба они одинаковы. Если бы кто-то отправил два разных значения, то семантически это выглядело бы как попытка изменить идентификатор записи, что, безусловно, недопустимо. Это просто проверка работоспособности.

и НЕ предоставляется клиентом

Клиент должен будет предоставить один из двух, чтобы вы могли идентифицировать запись для обновления. Вы можете вообще игнорировать item.Id, если хотите, и просто использовать значение id из URL-маршрута для идентификации записи. Однако , если вы это сделаете, вам также нужно будет сделать одно из двух:

  1. Добавьте строку кода, чтобы установить item.Id = id; перед попыткой прикрепить ее к контексту БД или
  2. Вместо добавления модели непосредственно в контекст БД, извлеките запись по ее id как отдельный объект и вручную обновите поля, которые вы хотите обновить.

В конце концов, если item.Id не предоставляется клиентом, то по умолчанию он будет 0, и Entity Framework не сможет присоединить этот объект напрямую без Id стоимость. Приведенные выше параметры предоставят это значение либо путем установки его непосредственно на объекте, либо путем использования существующего значения для повторно полученного объекта.

0 голосов
/ 28 мая 2020

POST обычно используется для создания объекта. PUT часто используется для обновления. А чтобы обновить его, нужно знать его личность. Скорее всего, long id является частью URL-адреса или строки запроса. И Item item - от тела. Эта проверка гарантирует, что объект, указанный в теле, соответствует тому, который указан в URL.

...