ASP.NET MVC – 如何使用视图模型

比方说,我有一个页面,允许编辑用户的细节,所以我有一个ViewModel是这样的:

public class UserViewModel { public string Username { get; set; } public string Password { get; set; } public int ManagerId { get; set; } public string Category { get; set; } } 

所以在我的EditUser操作中,我可以通过模型联编程序返回,然后我可以将其映射到域模型:

 public ActionResult EditUser(UserViewModel user) { ... 

但是,显示表单的页面还需要详细信息,例如pipe理员和类别列表,以便为这些字段提供下拉列表。 它也可能在边栏中显示其他用户的列表,以便您可以在正在编辑的不同用户之间进行切换。

那么我有另一个视图模型:

 public class ViewUserViewModel { public UserViewModel EditingUser { get; set; } public IEnumerable<SelectListItem> Managers { get; set; } public IEnumerable<SelectListItem> Categories { get; set; } public IEnumerable<SelectListItem> AllUsers { get; set; } } 

这是正确的方法吗? 他们都是视图模型? 如果是的话,是否有一个我应该使用的命名约定,以便我可以区分类似模型的虚拟机和仅包含页面数据的虚拟机?

我有这个全错吗?

我如何做到这一点快捷方式:

  1. 为页面上的每个表单创build单独的ViewModel类,然后使用PartialViews将这些类作为@{Html.RenderPartial("PartialName", Model.PartialModel);}
  2. 如果页面包含像html元素的东西,我为metas分隔类,并把它放在页面上的部分。
  3. rest的情况下,“我应该把这个分开的课?” 是你的判断。

所以,例如你有页面,有某种login/注册栏或popup任何。

 public class SomePageViewModel { public RegisterBarVM Register { get; set; } public LoginBarVM LoginBar { get; set; } public MetasVM Metas { get; set; } public string MaybePageTitle { get; set;} public string MaybePageContent { get; set;} [HiddenInput(DisplayValue = false)] public int IdIfNeeded { get; set; } public IEnumerable<SelectListItem> SomeItems {get; set;} public string PickedItemId { get;set; } } public class RegisterBarVM { public string RegisterUsername {get;set;} public string RegisterPassword {get;set;} //... } public class LoginBarVM { public string LoginUserame {get;set;} public string LoginPassword {get;set;} //... } //cshtml @model yourClassesNamespace.SomePageViewModel @{ Html.RenderPartial("LoginBar", Model.LoginBar); //form inside Html.RenderPartial("RegisterBar", Model.RegisterBar); //form inside using(Html.BeginForm()) { @Html.EditorFor(m => m.IdIfNeeded) @Hmtl.EditorFor(m => m.MaybePageTitle) @Hmtl.EditorFor(m => m.MaybePageContent) @Hmtl.DropDownListFor(m => m.PickedItemId, new SelectList(Model.SomeItems)) <input type="submit" value="Update" /> } } @section Metas { @{Html.RenderPartial("Meatas", Model.Metas} } 

关于编辑器模板Brad Wilsons博客 ,只是谷歌或寻找关于显示/编辑器模板和HtmlHelpers的堆栈资源。 它们对于构build一致的网站非常有用。

“视图模型”只是一种模式。 关于这个名字没有什么不可思议的,但是通常任何传递给视图的类(无论是简单地显示数据还是用于表单提交的目的)都被称为“视图模型”,并且被赋予像FooViewModelFooVM这样的名称来指示这是“观看模式”模式的一部分。

我不想对你太过于哲学,但是我认为关于游戏中的模式的一点点参考是有帮助的。 ASP.NET MVC显然足以鼓励MVC(模型 – 视图 – 控制器)架构模型。 在MVC中,Model是所有应用程序业务逻辑的容器。 Controller负责处理请求,获取模型,使用该模型呈现View并返回响应。 这似乎是一个很大的责任,但实际上框架处理大部分幕后,所以控制器是典型的(而且应该)非常轻的代码。 他们负责将所有东西连接起来的最低限度的function。 最后,视图负责创buildUI层,允许用户与模型中的数据进行交互。 它不是数据本身的责任,也不应该(ViewData / ViewBag在这里是一个相当大的违反,至less在开发人员实际使用的方式)。

所以,这意味着大部分的应用程序逻辑应该在你的模型中,通常这是一件好事。 但是,由于模型是应用程序数据的避风港,因此通常会保留在数据库或类似数据库中。 这会产生一些利益冲突,因为您现在需要在应该保留的数据与仅用于显示目的的数据之间开始平衡。

MVVM(模型 – 视图 – 视图模型)是一种与MVC平行的模式,它认识到单一模式到规则全部方法的固有问题。 这里我不会详细讨论,因为MVC不使用这种模式。 但是,大多数ASP.NET MVC开发者已经select了MVVM的View Model。 实质上最终是一个数据库支持的实体 (传统模型),然后通常是许多不同的视图模型,代表不同的状态。 这允许您的模型包含与持久性相关的业务逻辑,而视图模型包含与显示,创build和更新模型相关的业务逻辑。

我已经走了一段路,但是总的来说,你所做的是完全可以接受的。 事实上,这是很好的做法。 根据应用程序的需要创build尽可能多的视图模型,并使用它们实际存储视图所需的数据和业务逻辑。 (包括SelectList的东西,你的控制器和视图都不需要知道如何为下拉菜单创build一个SelectList 。)

我个人比较喜欢把所有需要的信息放在ViewModel中,这就是ViewModel的目的 – 为View提供所有的数据。 所以我的UserViewModel将包含ManagersCategories和所有用户的属性,控制器将填充这些集合,然后将ViewModelclosures到视图。

这基本上是你所做的 – 它只是从等式中删除额外的ViewModel。

我也看到其他程序员使用ViewData发送下拉列表到视图,但我不喜欢,因为ViewData不强types,而ViewModel是。