当您来自 MVVM 模式并从 MVC 模式(尤其是 ASP.NET MVC)开始时,我建议将“MVC”模式更好地视为“VMVC”,因为 MVC 中的“M”不是 Model 表示 MVVM 中的“M”。它实际上对应于 ViewModel。我不知道这是否代表了 MVC 的一般定义,但是当您使用 ASP.NET MVC 时,它是真实的,并且是最常用和最佳实践(尽管您不时在 SO 上看到域实体所在的示例或问题在视图中使用(这有时正是问题中描述的问题的原因)。
当我从一个 Visual Studio 模板创建 ASP.NET MVC 项目时,我通常做的第一件事是将创建的文件夹“Model”重命名为“ViewModel”。如果您查看模板代码对这些“模型”的作用,您会发现它们直接用于视图,它们具有用于输入验证、显示格式以及视图上的字段命名的数据注释。这些注释部分由 HTML 助手直接用于生成 HTML,并不代表域或业务逻辑。换句话说:它们是 Razor/HTML 视图的 ViewModel,就像您在 MVVM 中为 WPF/Silverlight/Phone7 中的 XAML 视图使用 ViewModel 一样。
域“模型”实际上不是 MVC 模式的一部分,因为它是 MVVM 模式的一部分。因此,当您将 MVVM 与 MVC 进行比较时,缩写词有些误导。作为一个非常简化的“翻译表”,可以说:
MVVM MVC
---- ---
M -> Domain Model not part of the pattern
V -> View (XAML) V -> View (HTML, Razor)
VM -> ViewModel M -> ViewModel
not part of the pattern C -> Controller
我不确定 MVVM 中控制器的相应内容。在 MVC 中,控制器通常是将域对象转换为 ViewModel,然后转换为视图(反之亦然)的模块 - 示意图:
ControllerActionForGetRequest ( params )
{
objects = GetDomainObject(params) - entities, queryables or DTOs
viewModel = CreateViewModelFromDomainObjects(objects)
view = CreateViewFromViewModel(viewModel)
}
ControllerActionForPostRequest ( viewModel )
// ModelBinder makes "viewModel" from HTML input fields, etc
{
if (IsValid(viewModel))
{
data = CreateDomainObjectsOrDtosFromViewModel(viewModel)
WriteData(data) - back to data store
RedirectToActionForGetRequest
}
else
GoBackToView
}
MVVM 的哪个部分有这个责任?我不知道。我见过这样的设计,其中 ViewModel 持有对存储库的一些引用,拉出模型(域模型)以填充其自己的属性并通过 ICommand 处理程序写回存储库。这意味着 MVVM 中的 ViewModel 也有责任成为“控制器”,而 MVC 中的 ViewModel 则要简单得多:它们或多或少只是带有元数据的属性包,用于为视图提供和格式化数据。
最后一点:我个人发现带有 WPF 的 MVVM 模式比 MVC 模式更难掌握。 ASP.NET MVC 从一开始就设计为支持 MVC 模式友好的开发,没有必要(甚至不可能)离开这种方式。这不是 WPF 的情况。最初的设计是在考虑视图和代码隐藏文件的情况下构建的,而不是使用 MVVM 模式。我经常发现很难将视图元素或属性绑定到 ViewModel 并且在代码隐藏文件中处理它要容易得多,因此有点违反 MVVM 原则。
我认为,当您有 MVVM 模式的经验时,进入 MVC 不会有任何问题。