论坛管理

EF Core Include

EF Core 通过 Include 实现 JOIN SQL 查询。

例如在展示论坛信息时需同时展示论坛拥有者的信息,所以 Include 了 Owner:

  1. [HttpGet]
  2. public IActionResult Index()
  3. {
  4. var forums = _dbContext.Forum.Include("Owner").ToList();
  5. return View(forums);
  6. }

Paritial View

因为论坛详情将在两个地方用到,所以使用了 Partial View

  1. 展示论坛详情

  2. 删除论坛时展示一下,帮助用户判断到底删不删

在 Views\Shared 文件夹下创建分部视图 _ForumDetail。

4 论坛和帖子管理 - 图1

  1. @using CoreBB.Web.Models
  2. @model Forum
  3. <div class="container col-6 offset-3" style="margin-top:120px">
  4. <div class="card border-info">
  5. <div class="card-header text-white bg-info">
  6. <strong>Forum Detail Information</strong>
  7. </div>
  8. <div class="card-body">
  9. <table class="table table-bordered table-striped">
  10. <tr>
  11. <th>Property</th>
  12. <th>Value</th>
  13. </tr>
  14. <tr>
  15. <td><strong>ID</strong></td>
  16. <td>@Model.Id</td>
  17. </tr>
  18. <tr>
  19. <td><strong>Name</strong></td>
  20. <td>@Model.Name</td>
  21. </tr>
  22. <tr>
  23. <td><strong>Owner</strong></td>
  24. <td><a asp-action="Detail" asp-controller="User" asp-route-name="@Model.Owner.Name">@Model.Owner.Name</a></td>
  25. </tr>
  26. <tr>
  27. <td><strong>Description</strong></td>
  28. <td>@Model.Description</td>
  29. </tr>
  30. <tr>
  31. <td><strong>Locked</strong></td>
  32. <td><input type="checkbox" asp-for="IsLocked" disabled="disabled" /></td>
  33. </tr>
  34. <tr>
  35. <td><strong>Create Date</strong></td>
  36. <td>@Model.CreateDateTime.ToShortDateString()</td>
  37. </tr>
  38. <tr>
  39. <td><strong>Operation</strong></td>
  40. <td>
  41. @if ((string)ViewData["Mode"] == "ShowingDetail")
  42. {
  43. if(User.IsInRole(Roles.Administrator))
  44. {
  45. <a class="btn-sm btn-primary" asp-action="Edit" asp-route-id="@Model.Id">Update</a>
  46. <a class="btn-sm btn-warning" asp-action="Delete" asp-route-id="@Model.Id">Delete</a>
  47. }
  48. <a class="btn-sm btn-success" asp-controller="Topic" asp-action="Create" asp-route-forumid="@Model.Id">Post Topic</a>
  49. }
  50. @if ((string)ViewData["Mode"] == "ConfirmingDelete")
  51. {
  52. <input type="submit" class="btn-sm btn-warning" value="Confirm" />
  53. }
  54. </td>
  55. </tr>
  56. </table>
  57. </div>
  58. </div>
  59. </div>

关于该分部视图的几个要点:

  1. 分部视图有自己的 View Model

  2. 在 Parent View(父视图)中通过 Html.Partial 设置传递给父视图的 View Model

  3. 通过设置 ViewData[“Mode”] 的值显示/隐藏 UI 元素

使用分部视图

在 Detail 视图里面使用分部视图:

  1. @using CoreBB.Web.Models
  2. @model Forum
  3. @{
  4. ViewBag.Title = "Forum Detail";
  5. ViewData["Mode"] = "ShowingDetail";
  6. }
  7. @Html.Partial("_ForumDetail", Model)
  1. 使用 @Html.Partial(“_ForumDetail”, Model) 渲染 Partial View,并传递 View Model

  2. Partial View 共享 Parent 的 ViewBag 和 ViewData

在 Delete 视图里面使用分部视图:

  1. @model CoreBB.Web.Models.Forum
  2. @{
  3. ViewBag.Title = "Delete Forum";
  4. ViewData["Mode"] = "ConfirmingDelete";
  5. }
  6. <h2 class="text-warning">Warning: All topics in this forum will be also deleted!</h2>
  7. <form asp-action="Delete" method="post">
  8. <input type="hidden" asp-for="Id" />
  9. @Html.Partial("_ForumDetail", Model)
  10. </form>

model vs Model

  • @model 语句用于设置视图的 View Model

  • Model 是视图 View Model 的具体引用

它俩的关系好比一个设置类型,一个引用实例。

帖子管理

与论坛不同,帖子间是有关系的,直接创建(Create)的是根帖子(root topic),通过回复(Reply)创建的是子帖子。 这些帖子一起构成了树形结构。

消息管理

消息显式时需依据发出/接收和已读/未读分为好几个类别,对于这类数据的传递有多种方式:

  • 直接传递整个 Message 集合,在 View 里面再具体筛选

  • 传递 List>

  • 使用 Dictionary>

课程中使用的方式是传递整个集合,在 View 里面筛选:

  1. @model IEnumerable<CoreBB.Web.Models.Message>
  2. @inject CoreBB.Web.Models.CoreBBContext _dbContext
  3. @{
  4. ViewBag.Title = "Messages";
  5. var user = _dbContext.User.Single(u => u.Name == User.Identity.Name);
  6. var unread = Model.Where(m => m.ToUserId == user.Id && !m.IsRead);
  7. var read = Model.Where(m => m.ToUserId == user.Id && m.IsRead);
  8. var unreadSent = Model.Where(m => m.FromUserId == user.Id && !m.IsRead);
  9. var readSent = Model.Where(m => m.FromUserId == user.Id && m.IsRead);
  10. }
  11. <div class="container" style="margin-top:60px">
  12. <div class="card border-info">
  13. <div class="card-header text-white bg-info">
  14. <strong>Messages</strong>
  15. <span>[Uread:@unread.Count()]</span>
  16. <span>[Read:@read.Count()]</span>
  17. <span>[Uread Sent:@unreadSent.Count()]</span>
  18. <span>[Read Sent:@readSent.Count()]</span>
  19. </div>
  20. <div class="card-body">
  21. <h3>Unread Messages</h3>
  22. @Html.Partial("_MessageList", unread)
  23. <h3>Read Messages</h3>
  24. @Html.Partial("_MessageList", read)
  25. <h3>Unread Sent Messages</h3>
  26. @Html.Partial("_MessageList", unreadSent)
  27. <h3>Read Sent Messages</h3>
  28. @Html.Partial("_MessageList", readSent)
  29. </div>
  30. </div>
  31. </div>

Lab_Files4.zip