何时使用ViewData而不是ViewModels?

12

假设你想开发你的控制器(Controller),使其使用ViewModel来包含Views所需渲染的数据,那么是否所有的数据都应该包含在ViewModel中?在什么条件下可以绕过ViewModel?

我提出这个问题是因为我处于这样一个位置:一些代码正在使用ViewData,而另一些则使用ViewModel。我希望向团队分发一组指南,以便他们知道何时使用ViewData,在何时使用ViewModel只是为了节省时间。我希望得到其他开发人员的意见,以确保我的指南不仅仅是出于个人偏见。

4个回答

9
只是为了进一步说明Fabian的评论;您可以按照本文中概述的步骤明确确保视图数据(ViewData)从未被使用。此文章。实际上,没有理由不使用模型(models)来处理所有事情。
如果你别无选择只能使用ViewData(例如在现有项目中);至少使用字符串常量来解析名称,以避免使用“魔法字符串”。类似这样的内容: ViewData[ViewDataKeys.MyKey] = myvalue; 事实上,我将其用于几乎任何需要“基于字符串”的内容(Session Keys、Cache Keys、VaryByCustom输出缓存键等)。

4
我们这里总是使用强类型视图模型,但会在一些小的地方(如局部视图)中使用 ViewData 来进行额外的修剪。这通常仅在我们重复使用局部视图时发生。"+1" 的意思是同意或支持前面的内容。 - jim tollan
1
@jim:同意,有一些情况(比如共享部分视图)是不可避免的;因此最好采取措施,在需要回退使用ViewData时不要自己给脚打枪 :) - DanP
什么是字符串常量和魔术字符串,并且为什么在共享的部分视图中使用ViewData是不可避免的? - Howiecamp
@Howiecamp:字符串常量至少是强类型的;因此,它们应该始终优先于使用字符串字面量来访问字典数据(这也为您提供了一个漂亮的键“注册表”,在一个固定位置上)。关于ViewData使用是“不可避免”的,这并不完全准确,但有时它是尝试创建某种基本的“上帝”模型来处理所有情况的最佳替代方案。希望这有助于澄清我的一些评论 :) - DanP

4

当您的视图变得更加复杂时,您可能希望考虑一种方法,即仅将模型用于输入字段,并使用ViewData支持视图需要呈现的其他内容。

至少有几个观点支持这种做法:

  1. 您拥有一个主页面,需要存在某些数据(例如标题中的类似StackOverflow用户信息的东西)。应用站点范围内的ActionFilter使得在每个操作后填充ViewData中的信息变得容易。如果将其放入模型中,则需要使站点中的每个其他模型都继承自基本模型(最初可能看起来不错,但很快就会变得复杂)。

  2. 当您验证已发布的表单时,如果存在验证错误,则可能需要将模型重新绑定(包括无效字段)回到视图并显示验证消息。这是可以接受的,因为输入字段中的数据会被发布并绑定到模型上,但是视图需要重新填充的任何其他数据呢?(例如下拉列表值、信息消息等)这些将不会被发布,而且在“周围”发布的输入值周围重新填充这些数据可能会变得混乱。通常更简单的方法是编写一个方法,该方法使用ViewData填充..视图数据。

根据我的经验,我发现这种方法很有效。

而在MVC3中,动态视图模型意味着不再需要使用字符串索引了!


2
我个人从不使用ViewData,所有的数据都通过Model传递,除非我在测试某些东西并且需要快速查看视图上的值。强类型!

我完全同意。魔术字符串最多只是丑陋的,最糟糕的情况下会带来麻烦。话虽如此,我也使用ViewData快速测试一些东西,但问题在于当它成为永久解决方案时! - DaveDev
是的 - 我完全同意。我甚至希望它能够被弃用。 - Pure.Krome
1
@Pure.Krome:你可以使用我在帖子中描述的方法来模拟折旧。在基础控制器中覆盖viewdata属性并添加[Obsolete()]属性将给您相同的结果(本质上)。 - DanP

1
在ASP.NET MVC 2中,ViewModel模式是首选方法。该方法充分利用了编译时静态类型检查的优势。结合编译mvc视图,将使您的开发工作流程更快、更高效,因为错误会在构建/编译时被检测到,而不是在运行时。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接