View Model Design And Use In Razor Views

4.41 (34 votes)

The recommended practice for transferring data to and from views in ASP.NET MVC is to use a View Model. But what is a View Model? How to you design one and how should they be used? This article attempts to provide answers to those questions.

In the olden days of web development, developers used RecordSet objects or more recently DataSets or DataTables as a means to transfer data from the database to a view template. The View template might have been a classic ASP file containing a mix of HTML and server-side code, or a Web Form consisting of databound server controls like a GridView or ListView. Regardless, the data is untyped and working with it usually consists of referring to items by index or by using "magic strings" to reference data container values that borrow from the schema of the database that the data originated from.

The MVC framework introduced the idea of strongly-typed views to ASP.NET, primarily to provide some Intellisense support to working with data in Views, compile-time type checking, remove the need to cast objects to other types in the View and to provide the ability to scaffold Views from the Model that the View derives from. Developers can still pass "untyped" data to Views using the ViewBag (or ViewData) mechanism. This is the quickest way to throw arbitrary values at a View. In fact, the default MVC 3 templated Home controller shows how to pass the string ""Welcome to ASP.NET MVC!" to the Index View using ViewBag.

Strongly-typed Views feature the @model directive at the top of a Razor ViewEngine file, which specifies the actual type that the View derives from:

@model ViewModelSample.Models.MyModel

This is added automatically when you use the View creation dialogue and select the option to make the View strongly-typed:

The Model class dropdown will become enabled, and will list all classes available to your project. In this particular example, I have added an ADO.NET Entity Data Model derived from the Northwind sample database to the MVC application being used for illustrative purposes. You can see the familiar auto-generated Product, Customer and Category classes in the dropdown list above.

When the View is compiled, a C# class is created:

public class _Page_Views_Home_Index_cshtml : System.Web.Mvc.WebViewPage<ViewModelSample.Models.MyModel>

The name of the class is derived from the name and location of the View file, and inherits from WebViewPage<TModel>, and it is this that provides the strong-typing and IntelliSense support etc. If no View Model type is set in a model directive, the type that is used instead is dynamic:

public class _Page_Views_Home_Index_cshtml : System.Web.Mvc.WebViewPage<dynamic>

What goes into the View Model?

This is the question that seems to be asked most often. So far as the Add View dialogue is concerned any class in the correct location is a candidate for a strongly-typed View. The collection of classes that were generated by the Entity Framework from the Northwind database are usually known as Domain Entities. It is not unusual to find Views deriving directly from these entities in tutorials and samples. One of the main reasons for this is that it is a quick route to generating demo-code. And sometimes it might even be appropriate where the system being developed is one that largely provides a CRUD application over those entities. If you want to create or update a Category in Northwind, all you really need is a CategoryName and Description property.

Data Annotation attributes are used to manage model validation at property level, as well as display labels and some aspects of scaffolding views. If the model class code is generated automatically, such as with the entity Framework, the file defining the domain entities is regenerated whenever the database is changed. You can use "buddy" or partial classes to apply attributes to domain entity properties. Here's a buddy class for the Category class:

public partial class Category

It is empty, but has its own attribute - the MetadataType attribute which associates the source of the metadata to be applied to the Category class. In this case, the attribute points to a type called CategoryMetadata whose definition is as follows:

public class CategoryMetadata
    [HiddenInput(DisplayValue = true)]
    public int CategoryId { get; set; }

    [Required, Display(Name = "Category Name")]
    public string CategoryName { get; set; }

Regardless how many times the edmx file is regenerated, the metadata attributes are safe from harm.

The real world, however, is not often as straightforward. Usually, Views are complex and include artefacts from more than one domain entity. And perhaps only a subset of any entity's properties. The solution is to create a class whose sole role is to act as a container for a specific View's data. Or a Model for the View, if you will, or a View Model. A common approach to producing a View Model is to compose it from some domain entities and perhaps a sprinkling of properties. A View for adding a new product to the Northwind database will need fields for all of the Product properties together with a way of specifying which Category the new Product object belongs to. Here's something that will do the job:

public class CreateProductViewModel

    public Product Product { get; set; }

    [Required, Display(Name = "Select a category")]
    public int CategoryId { get; set; }
    public SelectList Categories { get; set; }
    [Required, Display(Name = "Select a supplier")]
    public int SupplierId { get; set; }
    public SelectList Suppliers { get; set; }

The Product object comes directly from the domain entities generated by the Entity Framework. It will benefit from any validation or other attributes that may have been applied to a buddy class. The advantage of this approach is that code is reused in a DRY way, and the Product property needs little to no work once validated to prepare it for persistence by the data access layer.


There is a school of thought that domain entities are not the place for setting validation rules or scaffolding and labelling instructions, because these are are purely presentational concerns. Therefore the entity should not be exposed to the presentation layer, even as part of a composite View Model class. There are also security concerns related to mass-assignment vulnerabilities and over-posting attacks where malicious users can craft HTTP requests that include values for entity properties that are not included in the HTML form. The default model binding within MVC will cause those values to be updated or added along with legitimate fields. A built-from-the-ground up View Model solves both these concerns. Rather than include a domain entity (and all of its properties), you only include properties that are required for the specific View. Taking this approach, the CreateProductViewModel will look slightly different:

public class CreateProductViewModel
    [Required, Display(Name = "Product Name"), MaxLength(100)]
    public string ProductName { get; set; }
    [Required, Display(Name = "Quantity Per Unit"), MaxLength(20)]
    public string QuantityPerUnit { get; set; }
    [Required, Display(Name = "Price per unit")]
    public double UnitPrice { get; set; }
    [Required, Display(Name = "Reorder Level")]
    public int ReorderLevel { get; set; }
    [Required, Display(Name = "Select a category")]
    public int CategoryId { get; set; }
    public SelectList Categories { get; set; }
    [Required, Display(Name = "Select a supplier")]
    public int SupplierId { get; set; }
    public SelectList Suppliers { get; set; }

Only those properties that need to be are exposed through the highly customised Vew Model. The Product class has a Discontinued property - a bool. This highly customised View Model doesn't include that property so any attempt to set the Discontinued value by over posting using the revised View Model will not work - so long as the parameter to the Controller Action accepts the View Model and not a Product object. So this approach helps to ensure separation of concerns and offers some additional security, but it means that the values posted to the controller need to be mapped to an entity to be persisted. The data layer deals with Product objects, not View Models. For fairly simple objects, that should be too much trouble:

public ActionResult Create(CreateProductViewModel model)
    if(ModelState.IsValid) {
        var product = new Product {
                          ProductName = model.ProductName,
                          CategoryID = model.CategoryId,
                          SupplierID = model.SupplierId,
                          QuantityPerUnit = model.QuantityPerUnit
        return RedirectToAction("Index");
    return View(model);

However, mapping View Models to entities is made a lot simpler using a tool - AutoMapper, which is described as a convention-based object mapper. In other words, it maps one object (the View Model) to another (the Entity) based on the convention of properties on each object being named the same. It's actually more flexible than that - you can tell it to map mismatched properties too. AutoMapper is available from Nuget. You can access it within Visual Studio by going to Tools > Library Package Manager > Package Manager Console, then typing

PM> Install-Package AutoMapper

Once it has installed successfully, you simple create a mapping between two objects, then sit back:

public ActionResult Create(CreateProductViewModel model)
    if(ModelState.IsValid) {
        var product = Mapper.Map<CreateProductViewModel, Product>(model);
        return RedirectToAction("Index");
    return View(model);

My preference is to generate View Models specific for particular Views. While this may involve extra coding - and some might say a duplication of properties across entities and View Models, AutoMapper helps to minimise the additional work involved.


Date Posted:
Last Updated:
Posted by:
Total Views to date: 80063


- Zeljko

Shouldn't the line:
Mapper.CreateMap<CreateProductViewModel, Product>();
be called outside of the controller, at startup of the application?

- Mike


Yes, you are right - thanks. The code here is example only, but I will amend things to make that clearer.

- Zeljko

And something else regarding Automapper... Though I use it like you to map the viewmodel to the model, the author of Automapper doesn't think it's appropriate. He says Automapper was designed to 'flatten' the model (model to viewmodel conversion) but not the way round.

- Jules Bartow


You have the most cogent intro to ViewModels anywhere. Thank you.

However, inserts are easy. Most introductions seem to avoid the more difficult updates like the plague.

I'm looking for the next step in your excellent explanation with a similar walkthrough of using Lambda selection of joined tables between complex types with updates where a ViewModel represents subsets of multiple domain entities including Table per Type (TPT) inheritance with 1:0..1 relationships and the corresponding attaches and entry state changes using DbContext in Razor MVC pages.

Can you hold our hands (virtually) and coach us through the rest of the basics? Please.

I want to make ancestor errors and foreign key constraint violations a thing of the past.

- Mike


That's more of an Entity Framework topic than an ASP.NET one.

- Zipper

Great article Mike.

Any chance you can show how to retrieve the data as well as update it? I have yet to find a good example of all three scenarios on a semi-complex ViewModel (like yours which is perfect by the way in terms).


- Andi

I would like some property inheritance property. Something like that in your ViewModel:

public string ProductName { get; set; }

Because i feel, that no one can have the properties in sync

- Donald

Hi, May I please ask what the disadvantages of using the property directly are. I was referred to this blog from another where they said you are subject to Model Injection. Please clarify on this and how it can be done. I have another example I saw where their ViewModel derives a ViewModelBase<T> where T is the domain entity. So instead of have standalone backing properties, they have a ModelObject which is actually your domain entity. What is the best way of using your view models?

- Mike


It would be useful if you said which blog referred you here so I can try to understand what they are talking about.

Recent Comments

Ghazanfar 30/01/2016 06:43
In response to Getting Started with ASP.NET MVC 5 using Visual Basic
Nice working. Please keep it up to convert csharp code into Its very helpful for vb...

sara 29/01/2016 09:39
In response to Simple Login and Redirect for ASP.NET and Access
Hi there, I am trying to validate and check for inputs entered. When I don't enter any inputs and...

Martin Thatcher 28/01/2016 17:28
In response to MVC 5 with EF 6 in Visual Basic - Advanced Entity Framework Scenarios
A small typo I think. In the code section that begins Function Index(ByVal SelectedDepartment As As...

Suresh_thefame 28/01/2016 08:03
In response to Sessions and Shopping Carts

Andrey Kurdyumov 28/01/2016 05:47
In response to ASP.NET 5: Uploading files with ASP.NET MVC 6
@Lee IFormFile has OpenReadStream(): Stream method...

Alisa 27/01/2016 18:37
In response to A Better Way To Export Gridviews To Excel
Thanks for this example! I am also asking about the date fields having to be re-formatted when the a...

Dan Buckley 27/01/2016 00:47
In response to What ASP.NET Can And Cannot Do
New to all things programming, this was very helpful and clear. Please write more....

satyabrata 26/01/2016 16:16
In response to Request.Form Is Empty When Posting To ASPX Page
Thank you....

david sanchez 26/01/2016 09:51
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Thanks! This line " <img src="~/images/@Model.FilePaths.First(f => f.FileType == alt="" />" an...

Bryon 25/01/2016 15:06
In response to Windows Authentication With ASP.NET Web Pages
Was hoping this would help solve the issues I'm having. Then I saw the dates and new it was too old....