在ASP.NET MVC 模型中 选择最好的方法将多个model(数据模型)传递到视图
前提介绍
这个文章我们要讨论,在ASP.NET MVC模型的项目中,怎么选择一个最有效的方式来将多个数据模型(models)传递到视图(view)中。我们已经在之前的文章“在一个视图中使用多个模型”中,介绍了下面六个方式,“ViewModel,Partial View, Tuple, ViewData, ViewBag 和TempData”. 我们在特定的情境中进行选择哪一种方法时,可能会有疑惑。在这篇文章中,我会分享一下我在这个问题上的发现。
如果你还没有读过之前的文章“在一个视图中使用多个模型”,请先查看,因为这篇文章是建立之前那篇的基础之上的。之前的文章中有详细的讨论我们应该如何将多个数据模型(models)传递到视图,并且有ASP.NET MVC4应用的演示例子. 它会帮助你理解以下文章的内容。
方法的总体介绍
所有的在前一篇文章中介绍的六种方法都有各自的优点和不足。需要根据当在某个特定的情景中来选择,而且这明显也是一个争论的话题。在做任何决定之前,我们需要将需求完全辨认清楚,然后,我们就只需要对比这些方法的优缺点来进行选择。这篇文章中,我会整理这些方法从最常用的在ASP.NET MVC应用中的到最不常用的:
1,ViewModel
2,Partial View
3,ViewBag
4,ViewData
5,TempData
6,Tuple
注意:一个应用中可能会选择用到多种方法,这是根据应用在某一个特定环境的需求的之上的。我们需要考虑每一个当前坏境中最合适的方法。
接下来,我们详细讨论这些方法,包括他们的使用和有关的优缺点。
ViewModel
ViewModel 是一个允许我们在企业级应用程序中将多个models传递到视图的一个模式。它能为每一个视图的需要,将多个models(数据模型)集合起来或者将models的各种属性准确包含在内。ViewModel 不应该有方法函数。它是一个某个视图所需要的属性的集合。
典型使用:
ViewModel是在企业级程序应用中,最广泛使用的用来将多个model传递到视图的方法。这是一个当你需要在视图中打印或使用多个数据模型的属性时可以使用的标准的方式(也适用在Partial View中)。
优点:
- ViewModel 允许我们将多个类型的数据模型(models)当成一个类型数据模型来加载一个视图。
- 很棒的智能支持和编译阶段的在视图页面的错误检测功能。
- 使用ViewModel的话,视图只能获得它所需要的数据,这也对安全问题有好处。核心的数据模型不会暴露给用户。
- 如果在核心的数据模型中有什么改变,你不需要在视图的代码中再修改,你只需要修改系那个管的ViewModel。
- 用这个方式,ViewModel 促进了应用中的松耦合。
缺点:
ViewModel 在数据模型(Models)和视图(Views)之间又增加了一层,所以它就增加了一点复杂度。所以对于一些小的或者演示例子的应用,我们可以使用Tuple 或者别的简单的方式。
Partial View
一个Partial View 是一个你可以包含在一个父视图的子视图。在很多例子中,我们遇到这样一个情景,几个视图共享/共有一个演示部分,这个部分就是一个分开的partial view 并且嵌入用在别的视图中。
典型使用:
这个方法如此频繁地和ViewModel一起使用在企业级应用程序中。它是使用在你需要在多于一个视图页面中分享相同的一段代码(Razor Or HTML)时.
优点:
- 提高了视图代码在程序中的重用性。
- 对于单一页面(Single Page Application)应用非常有用。
- 你也可以在Partial View中使用ViewModel。
- 使用Partial View,你能够使用AJAX来更新一部分页面而不刷新整个页面。
缺点:
- 如果使用很多的话,视图变成了一个很多Partial View的集合,所以有时候可读性会差一点。
ViewBag
ViewBag 是一个来自ControllerBase类的动态属性。ViewBag 是以name/value的形式被内部存储在dictionary中。它使用新的才c# 4.0的动态特性,所以ViewBag不用为数据类型做类型转换。
典型使用:
ASP.NET MVC 3.0和之后的版本中,当一个成员不能直接关联到视图并且不适合使用Model时,应该使用ViewBag(一个ViewBag应该是一个封装了业务数据和行为的类)。典型的例子是使用ViewBag.Title设置页面的标题, 或者在视图中显示信息ViewBag.Message等。
优点:
- 使用ViewBag, 我们可以很省事的把数据从控制器发送到视图。
- ViewBag的语法比ViewData好用,不需要使用键值Key。
- ViewBag 不需要做数据类型的类型转换。
缺点:
- 它只用于单方向的传递数据,即从控制器到视图。
- ViewBag的值只能在当前的请求中有效,它的值不能在多个请求之间之久,意味着如果有Redirection(重导),ViewBag的值变成空。
- 过度使用ViewBag当然是一个不好的做法。不推荐使用在企业级的应用程序中,尽管有时候它被用在传递少量的数据。
- 没有智能支持和编译阶段检测错误的功能。
ViewData
ViewData是定义在ControllerBase类中的一个属性变量(类型为ViewDataDictionary 类)。存在ViewData中得值需要进行类型转换,转到他们在视图中的类型。在ViewData中存的值需要使用键值Key才能访问。
典型使用:
在ASP.NET MVC版本1和2中,ViewData是和ViewBag的用途一样的。微软为了更新的版本支持ViewData,但是ViewBag提供了更多好处,在最新的版本MVC中最好不使用ViewData。
优点:
- 使用ViewData我们能使用内置的属性伴随着键值Key,把数据从控制器传递到视图中。
缺点:
- 只是应用于单方向的数据传递,也就是从控制器到视图。
- ViewData的值只能在当前的请求中有效,它的值不能在多个请求之间之久,意味着如果有Redirection(重导),ViewData的值变成空。
- 过度使用ViewData当然是一个不好的做法。不推荐使用在企业级的应用程序中,尽管有时候它被用在传递少量的数据。
- 语法要使用键值Key,使得它不如ViewBag的可读性,ViewBag使用属性类型的语法。
- 没有智能支持和编译阶段检测错误的功能。
TempData
TempData是定义在ControllerBase类中的一个属性变量,它的类型是TempDataDictionary类。在TempData中存储的值需要进行类型转换为视图中的所需类型,并且该值是通过键值Key进行获取。它跟ViewData很相似,但是不同的是,它允许我们在一个控制器中接受数据从另一控制器,并从一个行为函数到另一个行为函数(Action)。因为它是通过在内部使用会话变量实现的,所以它有这样的功能。
典型使用:
无论你什么时候需要保持一些信息直到一个接着的后来的请求,使用TempData都是很好的方法。它应该在你需要保持例如验证信息,错误信息,或者一些小的不包含敏感数据信息的时候使用。因为它能保证会话来传递变量,所以你不应该把敏感的信息存放在TempData。
优点:
- 你可以从一个控制器传递数据到另一个控制器或者从一个Action传递到另一个Action。
缺点:
- 可能会如上面讨论的那样,引起一些安全隐患。
- 它需要进行类型转换和检测Null值来避免错误。
- Visual Studio中没有智能支持。
Tuple
Tuple 是一个在.NET Framework 4.0中出现的一个新的类。它是一个有序的序列,不可更改的,大小固定的各种不同(允许我们进行对多个数据类型进行组合)对象的集合。
典型使用:
它可能会对小的或者演示用例的程序合适。Tuple是一个C#语言的新特性,在特定的场景中使用,但是如果你在MVC中使用,你应该只在你需要建立ViewModel的时候使用。
优点:
- 它提供了一个可以整合多个类型的而不需要新创建类的方式(ViewModel)。
- 它是一个对ViewModel的快速补救措施,而且需要更少的代码编写。
缺点:
- Tuple 是大小固定的最多8个项目。
- 值被以item1, item2...形式记录,很难识从代码中识别变量。
- Visual Studio中没有很棒的智能支持。
总结
这个文章中,我们学习了如何选择最好的来传递多个数据模型models到视图的方法,希望这篇文章能帮助你去理解和在你自己的应用中有效的使用这些概念。非常欢迎你的在这方面的任何疑问和评论。谢谢。