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
相关产品推荐
相关产品推荐

