Edit: I updated this answer on my Blog:
http://www.samwheat.com/post/The-function-of-ViewModels-in-MVC-web-development
My answer is a bit lengthy but I think it is important to compare view models to other types of commonly used models to understand why they are different and why they are necessary.
To summarize, and to directly answer the question that is asked:
Generally speaking, a view model is an object that contains all the properties and methods necessary to render a view. View model properties are often related to data objects such as customers and orders and in addition, they also contain properties related to the page or application itself such as user name, application name, etc. View models provide a convenient object to pass to a rendering engine to create an HTML page. One of many reasons to use a view model is that view models provide a way to unit test certain presentation tasks such as handling user input, validating data, retrieving data for display, etc.
Here is a comparison of Entity models (a.ka. DTOs a.ka. models), Presentation Models, and View Models.
Data Transfer Objects a.k.a “Model”
A Data Transfer Object (DTO) is a class with properties that match a table schema in a database. DTOs are named for their common usage for shuttling data to and from a data store.
Characteristics of DTOs:
- Are business objects – their definition is dependent on application data.
- Usually contain properties only – no code.
- Primarily used for transporting data to and from a database.
- Properties exactly or closely match fields on a specific table in a data store.
Database tables are usually normalized therefore DTOs are usually normalized also. This makes them of limited use for presenting data. However, for certain simple data structures, they often do quite well.
Here are two examples of what DTOs might look like:
public class Customer
{
public int ID { get; set; }
public string CustomerName { get; set; }
}
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public DateTime OrderDate { get; set; }
public Decimal OrderAmount { get; set; }
}
Presentation Models
A presentation model is a utility class that is used to render data on a screen or report. Presentation models are typically used to model complex data structures that are composed of data from multiple DTOs. Presentation models often represent a denormalized view of data.
Characteristics of Presentation Models:
- Are business objects – their definition is dependent on application data.
- Contain mostly properties. Code is typically limited to formatting data or converting it to or from a DTO. Presentation Models should not contain business logic.
- Often present a denormalized view of data. That is, they often combine properties from multiple DTOs.
- Often contain properties of a different base type than a DTO. For example, dollar amounts may be represented as strings so they can contain commas and a currency symbol.
- Often defined by how they are used as well as their object characteristics. In other words, a simple DTO that is used as the backing model for rendering a grid is in fact also a presentation model in the context of that grid.
Presentation models are used “as needed” and “where needed” (whereas DTOs are usually tied to the database schema). A presentation model may be used to model data for an entire page, a grid on a page, or a dropdown on a grid on a page. Presentation models often contain properties that are other presentation models. Presentation models are often constructed for a single-use purpose such as to render a specific grid on a single page.
An example presentation model:
public class PresentationOrder
{
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
public string CustomerName { get; set; }
public Decimal OrderAmount { get; set; }
public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}
View Models
A view model is similar to a presentation model in that is a backing class for rendering a view. However, it is very different from a Presentation Model or a DTO in how it is constructed. View models often contain the same properties as presentation models and DTOs and for this reason, they are often confused one for the other.
Characteristics of View Models:
- Are the single source of data used to render a page or screen. Usually, this means that a view model will expose every property that any control on the page will need to render itself correctly. Making the view model the single source of data for the view greatly improves its capability and value for unit testing.
- Are composite objects that contain properties that consist of application data as well as properties that are used by application code. This characteristic is crucial when designing the view model for reusability and is discussed in the examples below.
- Contain application code. View Models usually contain methods that are called during rendering and when the user is interacting with the page. This code typically relates to event handling, animation, visibility of controls, styling, etc.
- Contain code that calls business services for the purpose of retrieving data or sending it to a database server. This code is often mistakenly placed in a controller. Calling business services from a controller usually limits the usefulness of the view model for unit testing. To be clear, view models themselves should not contain business logic but should make calls to services which do contain business logic.
- Often contain properties that are other view models for other pages or screens.
- Are written “per page” or “per screen”. A unique View Model is typically written for every page or screen in an application.
- Usually derive from a base class since most pages and screens share common properties.
View Model Composition
As stated earlier, view models are composite objects in that they combine application properties and business data properties on a single object. Examples of commonly used application properties that are used on view models are:
- Properties that are used to display application state such as error messages, user name, status, etc.
- Properties used to format, display, stylize, or animate controls.
- Properties used for data binding such as list objects and properties that hold intermediate data that is input by the user.
The following examples show why the composite nature of view models is important and how we can best construct a View Model that efficient and reusable.
Assume we are writing a web application. One of the requirements of the application design is that the page title, user name, and application name must be displayed on every page. If we want to create a page to display a presentation order object, we may modify the presentation model as follows:
public class PresentationOrder
{
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
public string CustomerName { get; set; }
public Decimal OrderAmount { get; set; }
public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}
This design might work… but what if we want to create a page that will display a list of orders? The PageTitle, UserName, and ApplicationName properties will be repeated and become unwieldy to work with. Also, what if we want to define some page-level logic in the constructor of the class? We can no longer do that if we create an instance for every order that will be displayed.
Composition over inheritance
Here is a way we might re-factor the order presentation model such that it becomes a true view model and will be useful for displaying a single PresentationOrder object or a collection of PresentationOrder objects:
public class PresentationOrderVM
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business properties
public PresentationOrder Order { get; set; }
}
public class PresentationOrderVM
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business properties
public List<PresentationOrder> Orders { get; set; }
}
Looking at the above two classes we can see that one way to think about a view model is that it is a presentation model that contains another presentation model as a property. The top-level presentation model (i.e. view model) contains properties that are relevant to the page or application while the presentation model (property) contains properties that are relevant to application data.
We can take our design a step further and create a base view model class that can be used not only for PresentationOrders but for any other class as well:
public class BaseViewModel
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
}
Now we can simplify our PresentationOrderVM like this:
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public PresentationOrder Order { get; set; }
}
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public List<PresentationOrder> Orders { get; set; }
}
We can make our BaseViewModel even more re-usable by making it generic:
public class BaseViewModel<T>
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business property
public T BusinessObject { get; set; }
}
Now our implementations are effortless:
public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
// done!
}
public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
// done!
}