Id 与对象作为 Delete HTTP Post 中的参数。哪个更好?

Id vs Object as parameters in Delete HTTP Post. Which is better?

作为初学者,我正在尝试使用 ASP.net Core 实现一个简单的 CRUD。我的问题是一个名为 DeletePlayer() 的 HTTP post。请考虑下面我的代码:

型号:

public class Player
{
    public int PlayerId { get; set; }
    //... deleted unrelated code for shorter post ...
}

控制器:

public class PlayerController : Controller
{
    private readonly DataContext _database;

    public PlayerController(DataContext database)
    {
        _database = database;
    }
    
        //... deleted unrelated code for shorter post ...

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult DeletePlayer(int? id)
    {
        if (id == null || id == 0)
        {
            return NotFound();
        }
        var obj = _database.Players.Find(id);
        if (obj == null)
        {
            return NotFound();
        }
        _database.Players.Remove(obj);
        _database.SaveChanges();
        return RedirectToAction("PlayerIndex");
    }
}

查看:

@model Player_Simulation.Models.Player

<form method="post" asp-action="DeletePlayer">
<input asp-for="PlayerId" hidden />
<div class="border p-3">
    <div class="form-group row">
        <h2 class="text-black-50 pl-3">Delete Player</h2> 
    </div>
    <div class="row">
        <div class="col-12">
            <div class="form-group row">
                <div class="col-6">
                    <label asp-for="PlayerName"></label>
                </div>
                <div class="col-6">
                    <label asp-for="PlayerRating"></label>
                </div>
            </div>
            <div class="form-group row">
                <div class="col-6">
                    <input asp-for="PlayerName" disabled class="form-control" />
                </div>
                <div class="col-6">
                    <input asp-for="PlayerRating" disabled class="form-control" />
                </div>
            </div>
            <div class="form-group row">
                <div class="col-8 offset-2 row">
                    <div class="col">
                        <input type="submit" class="btn btn-danger w-75" value="Delete" />
                    </div>
                    <div class="col">
                        <a asp-action="PlayerIndex" class="btn btn-success w-75">Back</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

图形:

我的 PlayerController 中的 DeletePlayer(int?id) 不起作用,它给我 HTTP 错误 404。但是,如果我将其更改为:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult DeletePlayer(Player obj)
    {
        _database.Players.Remove(obj);
        _database.SaveChanges();
        return RedirectToAction("PlayerIndex");
    }

删除有效!所以我的问题是:

  1. 为什么 DeletePlayer(int?id) 不工作而 DeletePlayer(Player obj) 工作?
  2. 如果我想让 DeletePlayer(int?id) 起作用,我必须做什么?

如果有人能帮助我解决我的困惑,我将不胜感激!

1.Why doesn't DeletePlayer(int? id) work while DeletePlayer(Player obj) work?

尝试在DeletePlayer(int? id)HttpPost方法中设置断点,点击删除按钮时是否命中断点?

如果这个断点没有命中,说明路由有错误,路由没有找到这个action方法,需要检查请求url和action名称

如果遇到断点,检查id值,可能id为null,所以if条件会return一个NotFound错误。 id 为空的原因可能是请求 url (路由模板)不包含 ID 值,并且提交表单不包含 id 字段。因此,id 将为空。

您正在使用表单提交删除,这将尝试发送整个模型,因此 DeletePlayer(Player obj) 起作用。

2.What must I do if I want DeletePlayer(int? id) to work?

解决办法就是你在例子中看到的,就是在DeletePlayer方法中添加ActionName("Delete")属性。该属性为路由系统执行映射,以便包含 POST 请求的 /Delete/ 的 URL 将找到 DeletePlayer 方法。

结果:

从上面的例子我们可以看到,在删除Get页面中,请求url是https://localhost:5001/Player/Delete/2,点击删除按钮后,提交请求url会是https://localhost:5001/Player/Delete/2,所以在HttpPost方法中,我们可以从请求url(路由数据)中获取id值,而不是提交的表单

参考:https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/details?view=aspnetcore-5.0