asp.net-mvc ASP.NET MVC - 如何准确地使用视图模型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16548376/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.NET MVC - How exactly to use View Models
提问by littlecharva
Let's say I have a page that allows the editing of a user's details, so I have a ViewModel like this:
假设我有一个允许编辑用户详细信息的页面,所以我有一个这样的 ViewModel:
public class UserViewModel {
public string Username { get; set; }
public string Password { get; set; }
public int ManagerId { get; set; }
public string Category { get; set; }
}
So on my EditUser action I can have this passed back by the model binder and then I can map that to the Domain Model:
因此,在我的 EditUser 操作中,我可以让模型绑定器将其传回,然后我可以将其映射到域模型:
public ActionResult EditUser(UserViewModel user) {
...
However, the page that displays the form also needs details such as a list of Managers and Categories to provide dropdowns for those fields. It might also display a list of other users in a sidebar so you can switch between the different users you're editing.
但是,显示表单的页面还需要详细信息,例如经理和类别列表,以提供这些字段的下拉列表。它还可能在侧边栏中显示其他用户的列表,以便您可以在正在编辑的不同用户之间切换。
So then I have another view model:
那么我有另一个视图模型:
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; }
}
Is this the correct way to do it? Are they both View Models? If so, is there a naming convention I should use so I can distinguish between VMs that are like models and VMs that just contain data for the page?
这是正确的方法吗?他们都是查看模型吗?如果是这样,是否有我应该使用的命名约定,以便我可以区分类似于模型的 VM 和仅包含页面数据的 VM?
Have I got this all wrong?
我这一切都错了吗?
采纳答案by Mariusz
How I do this in shortcut:
我如何以快捷方式执行此操作:
- Create separate ViewModel class for each form on the page, then I render these classes with PartialViews as
@{Html.RenderPartial("PartialName", Model.PartialModel);}. - If page contains things like html metas I make separated class for metas and put it in section on the page.
- Rest cases like "should I put this in separated class?" is your judgement.
- 为页面上的每个表单创建单独的 ViewModel 类,然后我将这些类与 PartialViews 渲染为
@{Html.RenderPartial("PartialName", Model.PartialModel);}. - 如果页面包含诸如 html metas 之类的内容,我会为 metas 制作单独的类并将其放在页面上的部分中。
- 其他情况,例如“我应该将其放在单独的班级中吗?” 是你的判断。
So for example you have page which has some kind of login/register bar or popup whatever.
例如,您的页面具有某种登录/注册栏或弹出窗口。
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}
}
About editor templates Brad Wilsons Blogand just google or look for stacks resources about display/editor templates and HtmlHelpers. They all are very useful for building consistent websites.
关于编辑器模板Brad Wilsons 博客,只需 google 或查找有关显示/编辑器模板和 HtmlHelpers 的堆栈资源。它们对于构建一致的网站非常有用。
回答by Chris Pratt
"View Model" is just a pattern. There's nothing magical about the name, but generally any class being passed to a view (whether for simply displaying data or for the purposes of form submissions) is referred to as a "view model" and given a name like FooViewModelor FooVMto indicate that it's part of that "view model" pattern.
“视图模型”只是一种模式。这个名字并没有什么神奇之处,但通常任何传递给视图的类(无论是为了简单地显示数据还是用于表单提交)都被称为“视图模型”,并被赋予一个类似FooViewModel或FooVM表示它是一部分的名称那个“视图模型”模式。
I don't want to go too philosophical on you, but I think a little bit of reference about the patterns in play will be helpful. ASP.NET MVC obviously enough encourages an MVC (Model-View-Controller) architectural model. In MVC the Model is the container for all the application's business logic. The Controller is responsible for handling the request, fetching the model, rendering the View with that model and returning a response. That seems like a lot of responsibility but in actuality the framework handles most of this behind the scenes, so Controllers are typically (and should be) very light on code. They are responsible for the bare minimum amount of functionality to wire everything up. Finally, the View is responsible for creating the UI layer that allows the user to interact with the data in the Model. It is notresponsible for the data itself, nor should it be (ViewData/ViewBag is a pretty big violation here, at least in as much as the way it ends up being used by developers in practice).
我不想对你太哲学,但我认为一些关于游戏模式的参考会有所帮助。ASP.NET MVC 显然足够鼓励 MVC(模型-视图-控制器)架构模型。在 MVC 中,模型是所有应用程序业务逻辑的容器. 控制器负责处理请求、获取模型、使用该模型呈现视图并返回响应。这看起来像是很多责任,但实际上框架在幕后处理了大部分工作,因此控制器通常(并且应该)非常轻量代码。他们负责将所有东西连接起来的最低限度的功能。最后,View 负责创建 UI 层,允许用户与 Model 中的数据进行交互。它不对数据本身负责,也不应该负责(ViewData/ViewBag 在这里是一个相当大的违规行为,至少与开发人员在实践中最终使用它的方式一样多)。
So, that means the bulk of your application logic should be in your model, and typically that's a good thing. However, since the model is the haven of application data, it generally gets persisted in a database or similar. That creates some conflict of interest as you now need to start a balancing act between what data should be persisted and what data should only exist for the purpose of display.
因此,这意味着您的大部分应用程序逻辑应该在您的模型中,通常这是一件好事。然而,由于模型是应用程序数据的避风港,它通常会被持久化到数据库或类似的地方。这会产生一些利益冲突,因为您现在需要在应该保留哪些数据和应该仅出于显示目的而存在的数据之间开始平衡。
This is where view models come in. MVVM (Model-View-View Model), a somewhat parallel pattern to MVC, recognizes the inherent issues in a one-model-to-rule-them-all approach. I won't go into much detail here, because MVC doesn't use this pattern. However, most ASP.NET MVC developers have co-opted the View Model of MVVM. What you essentially end up with is a database-backed entity(the traditional model) and then usually many different view models that represent that entity in various states. This allows your model to contain the business logic that's relevant to persistence while the view model(s) contain the business logic relevant to displaying, creating and updating that model.
这就是视图模型的用武之地。MVVM(模型-视图-视图模型)是一种与 MVC 有点平行的模式,它认识到一个模型到规则-所有方法中的固有问题。我不会在这里详细介绍,因为 MVC 不使用这种模式。但是,大多数 ASP.NET MVC 开发人员都选择了 MVVM 的视图模型。你最终得到的是一个数据库支持的实体(传统模型),然后通常会有许多不同的视图模型来代表处于各种状态的实体。这允许您的模型包含与持久性相关的业务逻辑,而视图模型包含与显示、创建和更新该模型相关的业务逻辑。
I've gone off track a little, but the long and short is that what you're doing is perfectly acceptable. In fact, it's good practice. Create as many view models as your application requires, and use them to actually store the data and business logic necessary for your views. (That includes things like SelectLists. Neither your controller nor view should need to know how to create a SelectListfor a dropdown.)
我有点跑偏了,但总而言之,你所做的一切都是完全可以接受的。事实上,这是一种很好的做法。根据应用程序的需要创建尽可能多的视图模型,并使用它们来实际存储视图所需的数据和业务逻辑。(这包括SelectLists 之类的东西。您的控制器和视图都不需要知道如何SelectList为下拉列表创建。)
回答by Jason Berkan
I personally prefer to put all the information required for the page to render in the ViewModel, as that is the purpose of the ViewModel - to provide all of the data for the View. So my UserViewModelwould contain properties for Managers, Categoriesand AllUsersand the controller would fill those collections prior to passing the ViewModel off to the view.
我个人更喜欢将页面呈现所需的所有信息放在 ViewModel 中,因为这就是 ViewModel 的目的 - 为 View 提供所有数据。因此,我UserViewModel将包含和 的属性Managers,Categories并且AllUsers控制器将在将 ViewModel 传递给视图之前填充这些集合。
This is essentially what you have done - it just removes the extra ViewModel from the equation.
这基本上就是您所做的 - 它只是从等式中删除了额外的 ViewModel。
I have also seen other programmers use the ViewData to send the dropdown lists to the view, but I dislike that because ViewData is not strongly typed, whereas a ViewModel is.
我还看到其他程序员使用 ViewData 将下拉列表发送到视图,但我不喜欢这样做,因为 ViewData 不是强类型的,而 ViewModel 是。

