本实验演示如何创建 DTO,以及如何通过模型绑定将 HTML 表单数据转换为复杂对象。

创建 DTO

在 Models 文件夹内创建 Source.cs:

  1. using System.Collections.Generic;
  2. namespace MyWebApp.Models
  3. {
  4. public class Film
  5. {
  6. public int ID { get; set; }
  7. public string Name { get; set; }
  8. public int Year { get; set; }
  9. public Genre[] Genres { get; set; }
  10. public bool IsInStore { get; set; }
  11. }
  12. public class CreateOrUpdateDTO
  13. {
  14. public int ID { get; set; }
  15. public string Name { get; set; }
  16. public int Year { get; set; }
  17. public Genre[] Genres { get; set; }
  18. public bool IsInStore { get; set; }
  19. public Operation Operation { get; set; }
  20. }
  21. public enum Genre
  22. {
  23. Action,
  24. Adventure,
  25. Comedy,
  26. Drama,
  27. War
  28. }
  29. public enum Operation
  30. {
  31. Create,
  32. Update,
  33. Delete
  34. }
  35. }

不难看出 Film 是领域模型,CreateOrUpdateDTO 是数据传输对象(DTO)。留心一点就会发现它俩非常相似,只是 DTO 类多了一点信息(Operation 属性)。

创建控制器

创建包含 CreateOrUpdate action 的 FilmController。

FilmController.cs:

  1. using Microsoft.AspNetCore.Mvc;
  2. using MyWebApp.Models;
  3. namespace MyWebApp.Controllers
  4. {
  5. public class FilmController : Controller
  6. {
  7. [HttpGet]
  8. public IActionResult CreateOrUpdate()
  9. {
  10. return View();
  11. }
  12. [HttpPost]
  13. public IActionResult CreateOrUpdate(CreateOrUpdateDTO dto)
  14. {
  15. var film = new Film()
  16. {
  17. ID = dto.ID,
  18. Name = dto.Name,
  19. Year = dto.Year,
  20. Genres = dto.Genres,
  21. IsInStore = dto.IsInStore
  22. };
  23. if (dto.Operation == Operation.Create)
  24. {
  25. // create a new film ... Note: the ID from the dto will be ignored
  26. return View("Created");
  27. }
  28. else if (dto.Operation == Operation.Update)
  29. {
  30. // update the existing film by ID
  31. return View("Updated");
  32. }
  33. else
  34. {
  35. return View("Error"); // we don't implement the Error view now
  36. }
  37. }
  38. }
  39. }
  • 标注 [HttpGet] 的 action 响应 HTTP GET 请求,主要用于将用户导向填表的网页

  • 标注 [HttpPost] 的 action 响应 HTTP POST 请求,用于处理用户的表单提交请求

换句话说,[HttpPost] 标注的 action 执行实际的创建/更新操作。

创建视图

在创建 Views 文件夹下创建 Film 文件夹,然后依次添加如下视图。

CreateOrUpdate.csthml:

  1. <html>
  2. <body>
  3. <h1>Create or Update Film</h1>
  4. <hr />
  5. <form action="createorupdate" method="POST">
  6. <span>ID</span>
  7. <input type="text" name="id" /><br />
  8. <span>Name</span>
  9. <input type="text" name="name" /><br />
  10. <span>Year</span>
  11. <select name="year">
  12. <option value="2015">2015</option>
  13. <option value="2016">2016</option>
  14. <option value="2017">2017</option>
  15. <option value="2018">2018</option>
  16. </select><br />
  17. <span>Genre</span>
  18. <input type="checkbox" name="genres" value="action" /><span>Action</span>
  19. <input type="checkbox" name="genres" value="comedy" /><span>Comedy</span>
  20. <input type="checkbox" name="genres" value="war" /><span>War</span><br />
  21. <span>In Store</span>
  22. <input type="radio" name="isinstore" value="true" /><span>Yes</span>
  23. <input type="radio" name="isinstore" value="false" /><span>No</span><br />
  24. <input type="submit" name="operation" value="Create" />
  25. <input type="submit" name="operation" value="Update" />
  26. </form>
  27. </body>
  28. </html>

Created.cshtml:

  1. <html>
  2. <body>
  3. <h1>The Film is Created!</h1>
  4. </body>
  5. </html>

Updated.cshtml

  1. <html>
  2. <body>
  3. <h1>The Film is Updated!</h1>
  4. </body>
  5. </html>

Error.cshtml

  1. <html>
  2. <body>
  3. <h1>Oops, Something Is Wrong!</h1>
  4. </body>
  5. </html>

调试与观察

与其他实验不同,本实验的重点在于断点调试标注了 [HttpPost] 的 CreateOrUpdate,观察模型绑定的工作机理。

操作步骤如下:

  1. 在 HttpPost 第一行设置断点

  2. 运行程序,访问 http://localhost:5000/film/createorupdate

  3. 填写信息,提交表单

  4. 观察表单数据通过模型绑定后的 dto

2.5.4 Lab4 DTO - 图1