Когда я нажимаю кнопку удаления, я получаю сообщение об ошибке и не нажимаю контроллер удаления в ASP.NET Core с Entity Framework Core

Я пытаюсь удалить некоторую категорию, используя ASP.NET Core и Entity Framework Core. Нажимаю "удалить" выдает ошибку

Эта страница не работает. Если проблема не исчезнет, ​​обратитесь к владельцу сайта. HTTP-ОШИБКА 405

Если я попытаюсь выполнить отладку, она никогда не достигнет установленной мной точки останова. Он никогда не попадает в контроллер. Почему это?

Вот мой код — это контроллер:

using Microsoft.AspNetCore.Mvc;
using practiceBookstore.Data;
using practiceBookstore.Data.Repository.IRepository;
using practiceBookstore.Models;

namespace practiceBookstore.Controllers
{
    public class CategoryController : Controller
    {
        private readonly ICategoryRepository _categoryRepository;

        public CategoryController(ICategoryRepository categoryRepository)
        {
            _categoryRepository = categoryRepository;
        }

        public IActionResult Index()
        {
            List<Category> Categories = _categoryRepository.GetAll().ToList();
            return View(Categories);
        }

        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Create(Category category)
        {
            if (category == null)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                _categoryRepository.Add(category);
                _categoryRepository.Save();
                return RedirectToAction("Index");
            }

            return View(category);
        }

        public IActionResult Edit(int? id)
        {
            if (id == null || id == 0)
            {
                return NotFound();
            }

            Category? category= _categoryRepository.Get(u => u.CategoryId == id);

            if (category == null)
            {
                return NotFound();
            }

            return View(category);
        }

        [HttpPost]
        public IActionResult Edit(Category category)
        {
            if (category == null)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                _categoryRepository.Update(category);
                _categoryRepository.Save();
                return RedirectToAction("Index");
            }

            return View(category);
        }

        [HttpPost]
        public IActionResult Delete(int? id)
        {
            if (id == 0 || id == null)
            {
                return NotFound();
            }

            Category ?category= _categoryRepository.Get(c => c.CategoryId == id);

            if (category == null)
            {
                return NotFound();
            }

            _categoryRepository.Remove(category);
            _categoryRepository.Save();

            return RedirectToAction("Index");
        }
    }
}

Это индексная страница категории, на которой расположены кнопки редактирования и удаления:

@model List<Category>

<h1>Category List</h1>
<a asp-action = "Create" asp-controller = "Category" class = "btn bg-dark text-white">Create new Category</a>
<table class = "table table-bordered table-striped">
    <thead>
        <tr>
            <th>Name</th>
            <th>Display Order</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach(var i in Model)
        {
            <tr>
                <td>@i.Name</td>
                <td>@i.DisplayOrder</td>
                <td>
                    <a asp-action = "Edit" asp-controller = "Category" asp-route-id = "@i.CategoryId" class = "btn btn-success">Edit</a>
                    <a asp-controller = "Category" asp-action = "Delete" asp-route-id = "@i.CategoryId" class = "btn btn-danger">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>

Я использую шаблон репозитория для базы данных.

Вот IRepository:

using System.Linq.Expressions;

namespace practiceBookstore.Data.Repository.IRepository
{
    public interface IRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        T Get(Expression<Func<T, bool>> filter);
        void Add(T entity);
        void Remove(T entity);
        void RemoveRange(IEnumerable<T> entities);
    }
}

Вот реализация:

using Microsoft.EntityFrameworkCore;
using practiceBookstore.Data.Repository.IRepository;
using System.Linq.Expressions;

namespace practiceBookstore.Data.Repository
{
    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly ApplicationDbContext _db;
        internal DbSet<T> Dbset;

        public Repository(ApplicationDbContext db)
        {
            _db = db;
            this.Dbset = _db.Set<T>();
        }

        public void Add(T entity)
        {
            Dbset.Add(entity);
        }

        public T Get(Expression<Func<T, bool>> filter)
        {
            IQueryable<T> query = Dbset.Where(filter);
            return query.FirstOrDefault();
        }

        public IEnumerable<T> GetAll()
        {
            IQueryable<T> query = Dbset;
            return query.ToList();
        }

        public void Remove(T entity)
        {
            Dbset.Remove(entity);
        }

        public void RemoveRange(IEnumerable<T> entities)
        {
            Dbset.RemoveRange(entities);
        }
    }
}

Это ICategoryRepository:

using practiceBookstore.Models;

namespace practiceBookstore.Data.Repository.IRepository
{
    public interface ICategoryRepository : IRepository<Category>
    {
        void Update(Category category);
        void Save();
    }
}

Это реализация:

using practiceBookstore.Data.Repository.IRepository;
using practiceBookstore.Models;
using System.Linq.Expressions;

namespace practiceBookstore.Data.Repository
{
    public class CategoryRepository : Repository<Category>, ICategoryRepository
    {
        private readonly ApplicationDbContext _db;

        public CategoryRepository(ApplicationDbContext db) : base(db)
        {
            _db = db;
        }

        public void Save()
        {
            _db.SaveChanges();
        }

        public void Update(Category category)
        {
            _db.Update(category);
        }
    }
}

Когда я нажимаю «Удалить», я ожидал, что это будет код для удаления категории и перенаправления на индексную страницу.

Для удалений лучше использовать [HttpDelete] вместо [HttpPost].

MikeJ82 31.05.2024 11:18

Для маршрутизатора все ваши конечные точки заканчиваются одним и тем же URL-адресом. Попробуйте [HttpPost("Delete")] , [HttpPost("Create")] и т. д. в качестве атрибутов или, как указал @MikeJ82, используйте правильные HTTP-глаголы. Обратите внимание, что вам необходимо настроить вызывающего абонента на «Категория/Удалить», «Категория/Создать».

jeb 31.05.2024 11:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема здесь выглядит так: Вы вызываете метод контроллера, который поддерживает только запросы HTTP POST, а ваша кнопка удаления при нажатии поддерживает вызов метода HTTP GET, чтобы вызвать метод удаления, вы можете сделать следующее:

  1. оберните кнопку удаления в объект формы, чтобы инициировать публикацию:

    < form asp-action="Удалить" asp-controller="Категория" asp-route-id="@i.CategoryId" метод="post" style="display:inline;"> < button type="submit" class="btn btn-danger">Удалить </ form>

Это должно работать, и ваш запрос должен достичь контроллера, кроме того, есть еще одно решение, которое включает в себя javascript, и вы можете использовать методы onclick + вызов ajax: Сделайте свой метод удаления в контроллере HTTP-запросом на удаление или оставьте его для HTTP POST, но я предлагаю преобразовать его в HTTP DELETE REQUEST.

Объявление метода DELETE может выглядеть так:

[HttpDelete]
public IActionResult Delete(int? id)

и измените его оператор возврата From:

return RedirectToAction("Index");

К:

return Ok();

и представление может выглядеть так с помощью JS-кода:

@model List<Category>

<h1>Category List</h1>
<a asp-action = "Create" asp-controller = "Category" class = "btn bg-dark text-white">Create new Category</a>
<table class = "table table-bordered table-striped">
    <thead>
        <tr>
            <th>Name</th>
            <th>Display Order</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach(var i in Model)
        {
            <tr>
                <td>@i.Name</td>
                <td>@i.DisplayOrder</td>
                <td>
                    <a asp-action = "Edit" asp-controller = "Category" asp-route-id = "@i.CategoryId" class = "btn btn-success">Edit</a>
                    <button class = "btn btn-danger delete-category" data-id = "@i.CategoryId">Delete</button>
                </td>
            </tr>
        }
    </tbody>
</table>

@section Scripts {
    <script src = "https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        $(document).ready(function () {
            $('.delete-category').click(function () {
                var id = $(this).data('id');
                if (confirm('Are you sure you want to delete this category?')) {
                    $.ajax({
                        url: '/Category/Delete/' + id,
                        type: 'DELETE',
                        success: function () {
                            window.location.href = '/Category';
                        },
                        error: function (xhr, status, error) {
                            alert('An error occurred: ' + xhr.responseText);
                        }
                    });
                }
            });
        });
    </script>
}

Надеюсь, это помогло, и это то, что вы искали.

Причина такого поведения в том, что тег <a> не поддерживает запрос на публикацию. Вы можете получить это из различных тем обсуждения.

Таким образом, все решения осуществимы и просты, как с тегом <form> или javascript, но не могут быть с тегом <a>.

Другие вопросы по теме

Похожие вопросы

Не удалось найти свойство с именем «keyName» типа «MyClass» в ASP.NET Core OData 8.2.5
Сделайте снимок экрана, используя Directx11 под С#
Почему позже в скрипте массив объектов становится нулевым, даже после подтверждения того, что после инициализации он не равен нулю?
C# XUnit (.Net 8): параметр IFormFile в конечной точке, подлежащей тестированию, всегда принимается как нулевой
Как я могу запускать метод через определенные промежутки времени? System.Timers.Timer, кажется, теряет синхронизацию
Почему игровой объект игрока продолжает двигаться в воздухе, несмотря на то, что клавиши движения не нажимаются? (закрыто)
Выполняется ли Dispose of my Activity синхронно с кодом моего приложения?
Привязка WPF MVVM DataGrid к IEnumerable вызывает ошибки привязки к Int32
Как избежать бесконечного цикла перенаправления при объединении двух разных схем аутентификации (openIdConnect и ASP.NET Identity)?
Добавьте несколько синглтонов одного и того же класса обслуживания во внедрение зависимостей в .NET 8