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





Проблема здесь выглядит так: Вы вызываете метод контроллера, который поддерживает только запросы HTTP POST, а ваша кнопка удаления при нажатии поддерживает вызов метода HTTP GET, чтобы вызвать метод удаления, вы можете сделать следующее:
оберните кнопку удаления в объект формы, чтобы инициировать публикацию:
< 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>.
Для удалений лучше использовать
[HttpDelete]вместо[HttpPost].