介绍

在 ASP.NET Core 中, 我们使用 View(视图)渲染数据。视图渲染后返回 HTML 内容。被视图所渲染的数据称为 View Model(视图模型)。在本节中, 我们将学习强类型视图模型和两种弱类型视图模型。

强类型视图模型

如果没有明确说明,当我们提到视图模型时说的都是强类型视图模型。在设计视图时, 可以通过设置视图的 Model 属性为其指定视图模型类型。运行时,Model 属性的值是视图模型类型的实例,它就是实际的视图模型。

下面代码中,我们将视图的视图模型设置为我们上一节创建的 Actor 类,并在 HTML table 中渲染它的数据。

ASP.NET Core 的视图引擎名为 Razor,具体的 Razor 语法我们将在第四单元再讨论。

  1. @model HelloMVC.Models.Actor
  2. <html>
  3. <head>
  4. <title>Actor Detail</title>
  5. </head>
  6. <body>
  7. <h2>Actor Detail</h2>
  8. <table border="1">
  9. <tr>
  10. <td>ID</td>
  11. <td>@Model.ActorID</td>
  12. </tr>
  13. <tr>
  14. <td>Name</td>
  15. <td>@($"{Model.FirstName} {Model.LastName}")</td>
  16. </tr>
  17. </table>
  18. </body>
  19. </html>

@model HelloMVC.Models.Actor 表示将视图的 Model 属性的类型设置为 HelloMVC.Models 命名空间中的 Actor 类。视图的整体架构是使用 HTML 创建的,可以直接从前端设计好的静态页面复制过来。

由于视图类只有一个 Model 属性,因此每个视图最多只能有一个强类型视图模型。因此,如果想在单个页面上显示多个对象,就必须创建复合视图模型

例如,如果你想要显示导演的信息以及 ta 指导的所有电影,你可能就需要设计如下复合视图模型:

  1. public class DirectorFilmsViewModel
  2. {
  3. public Director Director { get; set; }
  4. public IList<Film> Films { get; set; }
  5. }

总结一下,在使用强类型视图模型时:

  • 如果视图只需渲染领域模型对象,我们可以使用领域模型类作为视图模型类

  • 如果视图需渲染多个对象,我们必须为视图创建复合视图模型类

弱类型视图模型

对于某些杂项信息,通常不值得为它们专门创建强类型视图模型类。例如,显式在 标签的页面标题,完全不必像下面这样小题大做为它一个属性就创建一个类:</p> <pre><code class="lang-csharp">public class HomePageViewModel { public string Title {get; set;} } </code></pre> <p>也不推荐将这种额外的属性附加到原本的强视图模型中去:</p> <pre><code class="lang-csharp">public class DirectorFilmsViewModel { public Director Director { get; set; } public IList<Film> Films { get; set; } public string Title {get; set;} } </code></pre> <p>这样看起来就很古怪,一个导演电影的视图模型类里面就不该莫名其妙包含一个 Title 属性。并不是说你不能这样做,但 ASP.NET Core 提供了一种更好的处理这类数据的方法 —— 弱类型视图模型。</p> <p>由于某些历史原因,有两种弱类型视图模型可以用:</p> <ol> <li><p><strong>ViewData </strong>属性:一个实现了 IDictionary<string, object> 接口的字典类</p> </li><li><p><strong>ViewBag </strong>属性:一个 dynamic 对象</p> </li></ol> <p>写入数据:</p> <pre><code class="lang-csharp">ViewData["film"] = new Film{Name = "Transformer", Year = 2017}; ViewBag.title = "Film Details"; ViewBag.film = new Film{Name = "Transformer", Year = 2017} </code></pre> <p>渲染数据:</p> <pre><code class="lang-html"><span>@((ViewData["film"] as File).Name)</span> <title>@ViewBag.title</title> <span>@ViewBag.film.Name</span> </code></pre> <p>通过 ViewData 传递的数据在渲染时经常需要进行手动转换,通过 ViewBag 传递的数据在渲染时由于没有智能提示,难免出现语法错误,所以要尽量少用弱类型视图模型,更不要用它们传递复杂对象 —— 那是强类型视图模型的工作。</p>