c# - 为什么 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);
}
解决方案
首先,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可修改。或者有人更改隐藏输入的值。
推荐阅读
- c++ - 在 C++ 中嵌入 V8 会导致与 libcpp 相关的“无法识别的外部符号”错误
- python-3.x - 有没有办法从 dict 播放歌曲?不和谐.py
- reactjs - 在树数据结构上使用递归函数嵌套material-ui表,如何对齐列?
- pandas - 带有 int32 数组的 Pandas Dataframe 到 PySpark Dataframe 错误
- c++ - 为什么 gcc 'UNIX' 和 'unix' 宏不是一回事?
- javascript - 通过 setter 存储的新属性值在执行前生效
- javascript - click onclicking 是什么风格?
- mysql - 处理一对多和多对一映射的问题
- javascript - setTimeout 设置为 0 时延迟约 100 毫秒
- c++ - 在Arduino中为二维指针数组赋值