Методы Details и Delete

Rick Anderson

Откройте контроллер Movie и просмотрите метод Details:

public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}
#endregion

Движок скаффолдинга MVC, который создал эти методы действия, добавил комментарий, показывая HTTP запрос, который вызвал метод. В данном случае это GET запрос с тремя URL сегментами: контроллером Movies, методом Details и значением id. Эти сегменты определены в Startup.

#region snippet_1
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});
#endregion

Code First упрощает поиск данных, используя метод SingleOrDefaultAsync. Важная функция безопасности, встроенная в метод, состоит в том, что код проверяет, чтобы поиск ролика состоялся до того, как с ним будет что-то сделано. Например, кто-то может ввести ошибку на сайт, изменив URL с http://localhost:xxxx/Movies/Details/1 на что-то вроде http://localhost:xxxx/Movies/Details/12345 . Если вы не сделали проверку на null, приложение выбросит исключение.

Изучите методы Delete и DeleteConfirmed.

public async Task<IActionResult> Delete(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
    _context.Movie.Remove(movie);
    await _context.SaveChangesAsync();
    return RedirectToAction("Index");
}

Обратите внимание, что метод HTTP GET Delete не удаляет указанный ролик, он возвращает представление, где вы можете произвести удаление (HttpPost). Выполнение удаления в ответ на GET запрос (редактирования, создания или любой другой операции, изменяющей данные) создает дыру в безопасности приложения.

[HttpPost] метод, который удаляет данные, называется DeleteConfirmed, чтобы дать HTTP POST методу уникальную сигнатуру или имя. Две сигнатуры метода показаны ниже:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)

// POST: Movies/Delete/
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)

CLR требует, чтобы у перегруженных версий методов была уникальная сигнатура параметров (то же самое имя метода, но другой список параметров). Однако здесь вам надо два метода Delete – один для GET и один для POST – и у них обоих одинаковая сигнатура параметров. (В качестве параметра они оба принимают целое int).

Есть два способа решить эту проблему. Во-первых, можно дать методам разные имена. Это то, что сделал механизм скаффолдинга в предыдущем примере. Однако это вызывает небольшую проблему: ASP.NET передает сегменты URL методу действия по имени, и если вы переименуете метод, роутинг не сможет найти его. Решение вы видели в примере: добавить атрибут ActionName("Delete") методу DeleteConfirmed. Этот атрибут выполняет передачу для роутинговой системы, так что URL, который включает /Delete/ для POST запроса найдет метод DeleteConfirmed.

Второй способ работы с методами, у которых одинаковые имена и сигнатуры, состоит в том, чтобы добавить POST методу специальный (не используемый) параметр. Это то, что мы сделали ранее, когда добавили параметр notUsed. Вы можете сделать то же самое и здесь с методом [HttpPost] Delete:

[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)
{
    var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
    _context.Movie.Remove(movie);
    await _context.SaveChangesAsync();
    return RedirectToAction("Index");
}
Поделись хорошей новостью с друзьями!
Следи за новостями!