我最近开始担任网络开发人员。我使用 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(使用前将#替换为@)