You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core+EF Core点击删除报405错误,无法触发Delete控制器

ASP.NET Core 分类删除功能HTTP 405错误问题

点击删除按钮时出现错误:

此页面无法正常工作。如果问题持续,请联系网站所有者。HTTP ERROR 405

调试时Delete控制器方法断点未命中,请求未到达控制器。

问题原因

  • 页面中删除按钮使用<a>标签,默认发送GET请求
  • 控制器的Delete方法标记了[HttpPost]属性,仅接受POST请求
  • 请求方法不匹配,导致ASP.NET Core返回405 Method Not Allowed错误

解决方案

方案1:用表单发送POST请求(推荐,符合安全规范)

修改分类列表页面的删除按钮,用表单包裹以发送POST请求:

<td>
    <a asp-action="Edit" asp-controller="Category" asp-route-id="@i.CategoryId" class="btn btn-success">Edit</a>
    <form asp-action="Delete" asp-controller="Category" asp-route-id="@i.CategoryId" method="post" style="display: inline-block;">
        <button type="submit" class="btn btn-danger" onclick="return confirm('确定要删除该分类吗?');">Delete</button>
    </form>
</td>

方案2:允许Delete方法接受GET请求(不推荐,存在安全风险)

若需保留<a>标签,可修改控制器的Delete方法,将[HttpPost]改为[HttpGet],但此方式会让删除操作暴露给GET请求,易被误触发或遭受CSRF攻击:

[HttpGet]
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");
}

相关代码参考

控制器代码

using Microsoft.AspNetCore.Mvc;
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);
    }
}

Repository实现类

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

CategoryRepository实现类

using practiceBookstore.Data.Repository.IRepository;
using practiceBookstore.Models;

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

内容的提问来源于stack exchange,提问作者Miran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:29:53