The community is working on translating this tutorial into Chinese, but it seems that no one has started the translation process for this article yet. If you can help us, then please click "More info".
ViewModels
在本系列教程中,我们已经多次用到视图了。但如果你阅读了其它关于ASP.NET MVC框架的资料,或者是有关MVC设计模式的资料,你也许会注意到——一个叫做“视图-模型(View-Model)”的东西经常会被提及。但模型(Model)和视图模型(ViewModel)二者之间有什么区别? 实际上,当向一个视图传递模型时,由于该模型被视图所使用,因此这个被传递的模型就被认为是一个视图模型。换句话说,没什么区别 —— 你可以互换地将模型用作视图模型。
There are, however, a lot of situations where you may want to create a specific ViewModel for a specific View. This can be to extend or simplify an existing Model, or because you want to represent something in a View that's not already covered by one of your models.
ViewModels are often placed in their own directory in your project, called "ViewModels". Again, this is just a convention and since ViewModels are just regular .NET classes, you are free to place them where ever you want to, but it often makes sense to follow these conventions. Some people also prefer to postfix the name of the class with the word ViewModel, e.g. "AddressViewModel" or "EditUserViewModel".
When to use a ViewModel?
Here are a couple of situations where you could benefit from a ViewModel:
To represent something in a View that's not already contained by an existing Model: When you pass a Model to a View, you are free to pass e.g. a String or another simple type, but if you want to pass multiple values, it might make more sense to create a simple ViewModel to hold the data, like this one:
public class AddressViewModel
{
public string StreetName { get; set; }
public string ZipCode { get; set; }
}
To access the data of multiple Models from the same View: This is relevant in a lot of situations, e.g. when you want to create a FORM where you can edit the data of multiple Models at the same time. You could then create a ViewModel like this:
public class EditItemsViewModel
{
public Model1Type Model1 { get; set; }
public Model2Type Model2 { get; set; }
}
To simplify an existing Model: Imagine that you have a huge class with information about a user. Perhaps even sensitive information like passwords. When you want to expose this information to a View, it can be beneficiary to only expose the parts of it you actually need. For instance, you may have a small widget showing that the user is logged in, which username they have and for how long they have been logged in. So instead of passing your entire User Model, you can pass in a much leaner ViewModel, designed specifically for this purpose:
public class SimpleUserInfoViewModel
{
public string Username { get; set; }
public TimeSpan LoginDuration { get; set; }
}
To extend an existing Model with data only relevant to the View: On the other hand, sometimes your Model contains less information than what you need in your View. An example of this could be that you want some convenience properties or methods which are only relevant to the View and not your Model in general, like in this example where we extend a user Model (called WebUser) with a LoginDuration property, calculated from the LastLogin DateTime property already found on the WebUser class:
public class WebUser
{
public DateTime LastLogin { get; set; }
}
From there on there are two ways of doing things: You can either extend this class (inherit from it) or add a property for the WebUser instance on the ViewModel. Like this:
public class UserInfoViewModel
{
public WebUser User { get; set; }
public TimeSpan LoginDuration
{
get
{
return DateTime.Now - this.User.LastLogin;
}
}
}
Or like this:
public class ExtendedUserInfoViewModel : WebUser
{
public TimeSpan LoginDuration
{
get
{
return DateTime.Now - this.LastLogin;
}
}
}
Summary
A ViewModel is basically just a Model passed to a View, but as outlined in this article, there are many ways of doing this - you can either use an existing Model, as it is, or create a new one, specific to the View in question.