首页 > 解决方案 > 为什么 ASP.NET Core MVC 添加的 Edit() 操作方法(POST)脚手架中的 ID 参数传递了两次?

问题描述

我正在使用 Visual Studio 2019 中的 ASP.NET Core MVC 5.0。我让脚手架使用 Entity Framework Core 生成具有 CRUD 操作的控制器。我看到有两种Edit()方法,方法的GET版本在数据库中查找实体并将其传递给Edit视图。到目前为止,一切都说得通。我有点困惑的是POST该方法的版本Edit()。这是它的签名和第一条语句的样子:

 [HttpPost]
 [ValidateAntiForgeryToken]
 public async Task<IActionResult> Edit(int id, [Bind("Id,Name")] Department department)
 {
      if (id != department.Id)
      {
                return NotFound(); 
      }
      // ... (Removed for brevity)
}

如果ID可以Department使用模型绑定绑定到实体,为什么需要第一个int id作为参数?我已经尝试将它与相等检查一起删除,并且编辑仍然有效。我还注意到我的Edit视图中有一个隐藏的输入类型:

 <input type="hidden" asp-for="Id" />

删除id参数后我也尝试删除。Edit()不知何故仍然有效。我想知道ID参数的用途,方法id == department.Id中的相等检查Edit()以及视图中的隐藏输入字段Edit。我实际上想使用视图模型而不是直接使用我的实体,BindAttribute但遇到了这种混乱。

我的实体被调用Department,它看起来像这样:

public class Department
{
        public int Id { get; set; }

        [Required(AllowEmptyStrings = false, ErrorMessage = "{0} is required")]
        [StringLength(maximumLength: 100, MinimumLength = 1, ErrorMessage = "{0} should be between {2} and {1} characters")]
        public string Name { get; set; }

        public List<Course> Courses { get; set; }
}

有关更多上下文,以下是 的GET版本Edit()

public async Task<IActionResult> Edit(int? id)
{
            if (id == null)
            {
                return NotFound();
            }

            var department = await _context.Departments.FindAsync(id);
            if (department == null)
            {
                return NotFound();
            }
            return View(department);
}

标签: c#entity-frameworkasp.net-core.net-coreasp.net-core-mvc

解决方案


首先,Edit View中的隐藏输入是在Post Edit方法中绑定department.Id。因为你的部门有Id属性,所以当你删除时<input type="hidden" asp-for="Id" />,url中的Id仍然会绑定到department.Id和int Id。如果department.Id不存在,db会创建一个新的。这里有一个demo:

老师:

public class Teacher
    {
        public int TeacherId { get; set; }
        public string TeacherName { get; set; }
        public int TeacherAge { get; set; }


    }

编辑:

<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="TeacherName" class="control-label"></label>
                <input asp-for="TeacherName" class="form-control" />
                <span asp-validation-for="TeacherName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="TeacherAge" class="control-label"></label>
                <input asp-for="TeacherAge" class="form-control" />
                <span asp-validation-for="TeacherAge" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

编辑方法:

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("TeacherId,TeacherName,TeacherAge")] Teacher teacher)
        {
            

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(teacher);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!TeacherExists(teacher.TeacherId))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(teacher);
        }

结果: 在此处输入图像描述

有时不是每个模型都有一个名Id为主键的属性,所以隐藏输入是必要的。

而id用来确保编辑的数据Id是正确的。例如,如果有人自定义页面,使Id可修改。或者有人更改隐藏输入的值。

这是两个演示: 在此处输入图像描述 在此处输入图像描述


推荐阅读