ViewModels in ASP.Net MVC

The MVC architecture is all about separating the various layers of the applications in some logical parts. But this separation enforces some of the constraints on developers such as how to pass data from Controller to View. There are various ways to send those data to View such as using ViewData, ViewBag or TempData, the other ways is passing this data through ViewModels.

The view models group one or more entities or properties into one logical object which can be consumed by Views in order to render the contents on the View. The purpose of the View Models is to group all the necessary information required to render a view at a single place. This enforces a clear separation of Concerns, putting the data manipulation & domain entities away from the Controller & View. Using view models helps to create a good & maintainable code. Along with maintainable code, View Models are very beneficial in following cases

  1. Group all drop down related entities at a single place
  2. Master details records
  3. Pagination
  4. Dashboard details
  5. CRUD operations in which forms involves lot more controls

Although, from the above discussion it seems to be a more complex concept what View Model is, but actually it’s not. A view model is a simple C#/ VB.Net class, which contains some properties; those may involve primitive data type properties, or an entity or a set of entity.

Let’s create a ViewModel for following screen

The screen contains a text box for Name field & a drop down list for State. So ideally View Model should contain 2 properties 1 for Name & other for text box. So while rendering a view the ViewModel should be

This class will serve as a view Model when the view is rendered. So the controller will contain following code to render this form.

The above code will return a new form with State drop down list filled with 1 value NY. If we look at the AccountRegistrationGetViewModel carefully, you may notice [Required] attribute. This is one of the Data Annotations attribute supported by ASP.Net. They help us to validate the input data.

Now let’s create a view

It will generate a View which will contain following markup

But after validations user should be able to view the errors also we should accept these values at the Action Methods into a ViewModel. So let’s design that ViewModel.

So now when data is posted to the server in a Controller, we should catch this data in AccountRegistrationPostViewModel  . Also In order to show errors we need to add a property, as follows.

So our controller method will be So if validations are exploited these will be shown to user as below.

                 This is how we can use ViewModels. Initially it may look complex to create separate view Model for each function but later when it come to maintain the code, you will find it very very easy to fix the changes rather than striking you head on hardcoded strings.

You can find the source here.

Why not to use ViewData, ViewBag or TempData !

There are various ways of passing data from Controller to View or vice versa. For example when passing some values to View we can use ViewData Or TempData Or ViewBag. We set the appropriate values for keys in one of these & we can access it on view where ever we need it. This approach is used very extensively in some books as well as many of the blog posts. Though it is very easy & handy to set the values in ViewData, it has some pitfalls.

Before, we will see how we can pass the values from Controller to ViewData. Consider following simple example which contains a drop down list & a date time which we need to display on View. For that purpose controller would look something like this

[HandleError]

public class HomeController : Controller

{

private ICountryRepository _countryRepository { get; set; }

public HomeController(ICountryRepository CountryRepository)

{

_countryRepository = CountryRepository;

}

public ActionResult Index()

{

ViewData[“Country”] = _countryRepository.GetCountryList();

ViewData[“CurrentDate”] = DateTime.Now;

return View();

}

}

Here in Home controller we are setting the values for 2 entities one is Country & other is CurrentDate. Country is a drop down list whereas CurrentDate will display the current date time. The GetCountryList() function here returns IEnumerable.

The view for above will be like this

<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage” %>

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>

Home Page

</asp:Content>

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>

Country : <%: Html.DropDownList(“Country”, ViewData[“Country”] as SelectList) %>

Current DateTime : <%: ViewData[“CurrentDate”]%>

</asp:Content>

Though this looks pretty simple, however we are doing a lot of hardcoded string passing which is not at all good. The main pain with passing hardcoded strings is they can never be cause on compile time. Passing hardcoded string is not a big problem, we can solve it by using string Constants. But ideally, string hardcode should be avoided in order to avoid future mess which may occur during the maintenance phase of the project. Also we need to consider situations where we may need to show more than 10 items on the view, are we going to keep all these items to ViewData ? Also, see how we need to cast ViewData[“Country”]  to SelectList in order to pass it to the DropDownList helper function. While using ViewData all across the application, we need to take this pain.

Though this post was all about not using ViewData, ViewBag or TempData, there are situations where we need to use these as we cannot use View Models there. We will discuss these things in later posts.