08 输入 Model 和防止重复 Post.mp4 (97.86MB)

__RequestVerificationToken

Tag Helper 会在

内自动添加一个隐式的 input,用于防止 CSRF(跨站请求伪造)。

  1. <form method="post">
  2. ...
  3. <button type="submit" name="save">保存</button>
  4. <input name="__RequestVerificationToken" type="hidden" value="CfDJ8MRDbUrpbqdIjRKQ1pLEGkphym9fk620w7Mnp-zhumPmrWEwDrk6cdR9q4Sju_AP_38Sp2ba-51KNWaRz2mXB-BXEegqNjwb8squcePSc3M43uiYnDrY8HzIumHvPCHoOOyGUHZwgShbYMZnOcz4jow" />
  5. </form>

可以通过 ValidateAntiForgeryToken 特性在后台对该 Token 进行验证:

  1. [HttpPost]
  2. [ValidateAntiForgeryToken]
  3. public IActionResult Create(StudentCreateViewModel student)
  4. {
  5. ...
  6. }

输入的 Model

  • Form
  • 导航到含有 Form 的 View

因为在 View 里面填写并提交的 Model 不包含的 Id 属性,所以如果 Create 方法使用 Student 类型作为 Model,MVC 框架会想尽办法在提交的信息里面找 Id 属性,进而导致出现意想不到的状况。

因此我们需要创建与 View 里面提交的 Model 属性一致的 Input Model。

StudentCreateViewModel:

  1. public class StudentCreateViewModel
  2. {
  3. public string FirstName { get; set; }
  4. public string LastName { get; set; }
  5. public DateTime BirthDate { get; set; }
  6. public Gender Gender { get; set; }
  7. }

ViewModel 的使用:

  1. [HttpPost]
  2. public IActionResult Create(StudentCreateViewModel student)
  3. {
  4. var newStudent = new Student
  5. {
  6. FirstName = student.FirstName,
  7. LastName = student.LastName,
  8. BirthDate = student.BirthDate,
  9. Gender = student.Gender
  10. };
  11. var newModel = _repository.Add(newStudent);
  12. return View("Detail", newModel);
  13. }

防止重复 Post

因为 Post 后地址依然是 /Home/Create,所以按下 F5 刷新网页,浏览器会重复提交信息。
image.png

Post-Redirect-Get

通过 Post-Redirect-Get 模式重定向防止重复提交。

  1. [HttpPost]
  2. public IActionResult Create(StudentCreateViewModel student)
  3. {
  4. var newStudent = new Student
  5. {
  6. FirstName = student.FirstName,
  7. LastName = student.LastName,
  8. BirthDate = student.BirthDate,
  9. Gender = student.Gender
  10. };
  11. var newModel = _repository.Add(newStudent);
  12. return RedirectToAction(nameof(Detail), new { id = newModel.Id });
  13. }

效果:
image.png

源码

Tutorial.zip