我们为什么使用 ViewModel?

2024-04-08

我最近开始担任网络开发人员。我使用 ASP .NET MVC 4 和 NHibernate。

在我的工作场所,我们严格要求使用视图模型在控制器和视图之间来回传输数据。并且视图模型不应包含模型的任何对象。 我知道它是控制器和视图之间的一层。

但我发现即使我们可以直接将模型的对象发送到视图(在大多数情况下),编写视图模型类也是重复且多余的。

例如,如果我想显示订单,我可以在控制器的操作中执行此操作 -

return View(Repository.Get<Order>(id));

但相反,我必须编写一个视图模型,用获取的订单填充它,然后将其传递给视图。

所以,我的问题是,当我们可以按原样使用模型的对象时,编写视图模型的目的是什么?


对于较小的项目,你是对的。我听到你的论点并表示同情 - 然而,这是有充分理由的,繁琐和重复的工作,特别是在更大和更复杂的应用程序中:

  • 在控制器操作中执行所有处理非常重要。然而在你给出的例子中,Repository.Get方法可能会返回一个延迟计算的值IQueryable对象,这意味着在评估视图之前数据库不会被命中。由于多种原因,这很糟糕。 (解决方法是调用.ToList仍在控制器中)。
  • “视图不应包含任何非表示性逻辑”和“您不应信任视图”(因为视图可能是用户提供的)。通过提供模型对象(可能仍连接到活动的 DatabaseContext),视图可以对数据库进行恶意更改。
  • 视图的数据显示并不总是与其模型的数据 1:1 映射,例如考虑用户详细信息页面:

    用户的 EF 模型对象代表其在数据库中的实体,因此它可能如下所示:User { UserId, UserName, PasswordHash, PasswordSalt, EmailAddress, CreatedDate },而“用户详细信息”页面上的字段将是User { UserId, UserName, Password, ConfirmYourPassword, EmailAddress }, 你看得到差别吗?因此,你cannot使用 EF 用户模型作为视图模型,您必须使用单独的类。

  • 模型操作的危险:如果您让 ASP.NET MVC(或任何其他框架)将模型绑定到传入的 HTTP POST 请求(以上面的用户详细信息示例),则用户可以通过伪造密码来重置任何人的密码UserId适当的价值。 ASP.NET 将在绑定期间重写该值,除非您专门对其进行清理(无论如何,这与创建单独的 ViewModel 一样繁琐),否则此漏洞将仍然存在。

  • 在多个开发人员以团队形式工作的项目中,重要的是一切都保持一致。某些页面使用定制 ViewModel 而其他页面使用 EF 模型是不一致的,因为团队没有共同的意识,事情必须记录下来并且通常是有意义的。出于同样的原因,单个开发人员无需在其源代码中放入过多的 XML 文档就可以逃脱,但在团队情况下,如果不这样做,您就会崩溃。

对于您的情况,我将与您分享一个轻微的解决方法,但请注意先决条件:

  • 您的观点可以完全信任
  • 您的视图仅包含表示逻辑
  • 您的应用程序主要是 CRUD
  • 您的视图与每个 EF 实体模型一一对应(即无 JOIN)
  • 您的视图仅处理 POST 表单的单个简单模型,而不是复杂模型(即对象图)

...那么你可以这样做:

  • 将所有单向、非表单相关的数据放入您的ViewData集合,或ViewBag在 MVC 4 中(甚至是通用的ViewData<T>如果你是铁杆)。这对于存储 HTML 页面标题以及与母版页共享数据非常有用。
  • 用你的完全评估并加载EF 型号作为您的View<TModel> models.

但请谨慎使用此方法,因为它可能会导致不一致。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我们为什么使用 ViewModel? 的相关文章

随机推荐

  • Spring 将表单的操作映射到控制器

    我是 Spring 框架的新手 我使用以下方法创建了一个控制器 RequestMapping fetch contactId public String getContact PathVariable contactId Long cont
  • 如何使antlr4完全标记化终端节点

    我正在尝试使用 Antlr 制作一个非常简单的解析器 它基本上标记了一系列 分隔标识符 我做了一个简单的语法 r STRUCTURE SELECTOR STRUCTURE SELECTOR ID STRUCTURE SELECTOR ID
  • Redis部署配置-主从复制

    目前我有两台服务器 我已经部署了基于node js Express JS的Web服务API 我正在使用 Redis 来缓存 JSON 字符串 将此设置部署到生产中的最佳选择是什么 我懂了here https stackoverflow co
  • 删除 WPF ListView/GridView 高亮镶边

    我有 WPF ListView 和 GridView 视图 我想删除行突出显示的任何痕迹 这段有用的代码可以在该网站的一个答案中找到
  • Android:以编程方式从设备管理器中删除我的应用程序?

    我正在尝试向我的应用程序添加一个按钮以将其从设备管理员中删除 并使用下面的代码 但我的应用程序崩溃了 Code 单击按钮 ComponentName devAdminReceiver new ComponentName this DemoD
  • 将金额转换为 Python 印度格式的单词

    如何将印度语中的金额转换为单词 我正在使用 num2words 库 但它在呈现 十万 和 千万 时呈现错误的单词集 例如 num2words 903614 55 lang en IN 其印刷 nine hundred and three t
  • Kendo mvc grid 内联编辑模式 DateTimePicker 模板给出错误

    我正在使用 Kendo UI mvc 网格来列出数据 我正在这个网格中进行内联编辑 我使用 EditorTemplate 作为日期时间字段 这样它将在内联编辑模式下为日期时间字段提供日期时间选择器 当我要单击 更新 按钮时 它会给我这样的验
  • 将较小的矩形合并为较大的矩形

    我有一个问题 我需要将小正方形合并成更大的矩形 假设我有一个 2D 网格 其中填充了随机 1 和 0 1 0 1 1 0 1 0 1 1 1 0 1 0 1 1 0 1 0 1 1 0 0 1 0 0 1 代表已填充的区域 我将它们绘制为屏
  • 无法解析配置“:app:debugRuntimeClasspath”的所有文件

    我正在尝试构建颤振应用程序 之前运行正常 但突然出现此错误 Execution failed for task app checkDebugAarMetadata gt Could not resolve all files for con
  • 如何控制 UISearchDisplayController 的 searchResultsTableView?

    我想知道如何控制所使用的表视图UISearchDisplayController 你不能覆盖searchResultsTableView的财产UISearchDisplayController 因为它是一个只读财产 我尝试过覆盖search
  • 如何使用 WiX 设置服务的恢复选项?

    我有以下 wxs 文件
  • 为什么发送电子邮件需要多个邮件服务器跃点?

    当我向某人发送电子邮件时 我认为 我的电子邮件被发送到我的家庭服务器 然后电子邮件被发送到目标服务器 最后被发送到我想要发送给的人 有时 这需要多次跳跃 这是让我困惑的一点 为什么这需要多跳 为什么邮件不能直接发送到目标服务器 例如 XMP
  • iPhone 的精灵表生成器? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 到目前为止 我一直在制作自己的 1024 1024 精灵表 将图像放置在 64 x 64 网格中 以帮助轻松识别每个精灵的位置和大小 不用
  • Google 地图 - 从 ROADMAP 中删除网格

    I m integrating the google map in my site It works fine However it shows grid like this 我想删除它以使地图更美观 任何人都知道如何删除它 Thanks
  • 如何使用 JPA CriteriaBuilder 查询执行外连接?

    我正在使用 JPA 2 0 Hibernate 4 1 0 Final 和 MySQL 5 5 27 我想构造一个 JPA 查询 每行返回两个实体 并且我想执行右外连接 这两个实体是 Entity Table name user uniqu
  • 无法从 Dropbox 检索图像

    你好 我有一个图像滑块 当我尝试从服务器检索图像时 图像会正确显示 http stthomasmountmtc org index html http stthomasmountmtc org index html 但是 当我尝试从 Dro
  • 我无法在 .NET MAUI 中显示带下划线的条目

    我曾在 Xamarin 平台工作过 现在正在学习 NET MAUI 尽管有很多相似之处 但我面临着某些问题 我无法按照 NET MAUI 文档声明的方式在 Android 设备上显示基本的输入控件 以下是输入字段的代码片段
  • C++ 和其他语言有小提琴类型的东西吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我记得曾经见过一个 jsfiddle 类型的东西 在线编译器 您可以在其中指定语言 c c asm 以及
  • 辅助阅读将列表视图中的项目显示为列表项 + 标题视图

    我正在自定义下拉刷新列表视图中实现可访问性 我的下拉刷新列表视图有一个标题视图 用于在下拉时显示更新状态 如果我的列表仅包含 5 个项目 Talkback 将其读取为 显示第 1 项 共 6 项 而不是 显示第 1 项 共 5 项 我认为总
  • 我们为什么使用 ViewModel?

    我最近开始担任网络开发人员 我使用 ASP NET MVC 4 和 NHibernate 在我的工作场所 我们严格要求使用视图模型在控制器和视图之间来回传输数据 并且视图模型不应包含模型的任何对象 我知道它是控制器和视图之间的一层 但我发现