The Model, the View, and the Dictionary

An object model for the view is better than a plain dictionary

Dino Esposito

October 30, 2009

10 Min Read
ITPro Today logo in a gray background | ITPro Today

CoreCoder

Languages: C#

ASP.NET VERSIONS: MVC

The Model, the View, and the Dictionary

An object model for the view is better than a plain dictionary

By Dino Esposito

ASP.NET MVC brings a blast of fresh air to theworld of ASP.NET programming and revolutionizes established and consolidatedpatterns and practices in web application development. ASP.NET MVC forces youto apply a web-specific variation to the classic Model-View-Controller pattern(MVC) in every page you write.

In ASP.NET MVC, you design URLs around the use-casediagrams resulting from preliminary analysis of user requirements. Such URLsdon't map to server page files but are associated with server-side actions andsubsequent results. In this article, I'll discuss how results may flow into theview after the requested action has completed. ASP.NET MVC provides built-intools you can use. I'll analyze and contrast the characteristics of each.

The (Well-Known?) MVC Dynamics

Much has been written about ASP.NET MVC since thefirst CTP in the fall of 2007. Most of this writing emphasizes the benefits ofthe MVC pattern versus the Page Controller model typical of ASP.NET Web Forms. It'shard to state that the MVC pattern is superior to the Page Controller pattern,which has fueled the ASP.NET platform for years. A much easier point to sustainis that the MVC pattern simplifies the implementation of features that more andmore developers consider essential today. Separation of concerns andtestability are two of the most popular features.

The MVC pattern was neither formalized for theASP.NET MVC platform nor for the web as a whole. Instead, the MVC pattern wasdevised two decades ago as a general paradigm to lead toward more structuredcode. At the time, applications were monolithic blocks of code where everythingtook place within the front end. The MVC pattern taught developers to think ofapplications as the combined effort of three actors: the controller, the view,and the model.

The view, which is the front end, receives any userinput and forwards such commands to the controller. The controller decides whatto do, and in doing so it interacts with the application model. Any actiontaken by the controller then updates the model. The view receives changes fromthe model and refreshes itself.

In a nutshell, this is the true dynamic of MVC. Andif you think about it for a moment, you can't help but realize that this isquite different from how ASP.NET MVC performs. Figure 1 shows the sequencediagram for the MVC pattern.

Figure 1: Sequence diagram for the classic MVC interaction model

The MVC Pattern for the Web

The web was still in the works when the first paperpresenting the MVC paradigm came out around 1980, so it's no surprise that theMVC model requires significant updates to work for a web application. Whendeveloping Java Server Pages (JSP), Sun reworked and adapted the MVC paradigm forthe web. The name of the resulting pattern is Model2, and it's what in theMicrosoft space today is generically labeled as MVC. Figure 2 shows thesequence diagram for the Model2 pattern and explains very well how things workin ASP.NET MVC.

Figure 2: Sequence diagram for the ASP.NET MVC interaction model

Even a quick comparison of Figure 1 and Figure 2proves that significant differences exist between the interaction model of thetwo patterns. In particular, in classic MVC the view and model know each otherand the two are tied together using an observer relationship. In ASP.NET MVC,the controller acts like a mediator between the two. The controller firstcommands a task and receives fresh data; next, it explicitly passes up-to-datedata to refresh the user interface down to the view. View and model don't knoweach other. View and controller are related but largely independent andautonomous, which guarantees ease of testing.

What's the Model in ASP.NET MVC?

Originally, the model actor was described as thecollection of data being worked on in the view and this definition justifiedthe link between view and model in classic MVC. In ASP.NET MVC, the viewreceives data directly from the controller in a format that may vary quite abit. As we'll see in a moment, data may flow into the view through a general-purposedictionary or through a strongly typed object model. Is this data container theincarnation of the model actor in ASP.NET MVC?

Originally, in MVC the data worked on in the viewcoincided with the application data model. Today, in a multi-layered solutionthe two elements are often quite different. The view-model is oftensignificantly different from the application data model. In WPF andSilverlight, in fact, the popular Model-View-ViewModel pattern (MVVM) is foundedon this basic fact. The view-model is sometimes made of data transfer objectsthat decouple the view from the application data model. So whether the modelactor is the view-model or the application data model remains an open point andis mostly a matter of personal perspective. Much more concretely tied toASP.NET MVC programming is how data flows into the view.

The ViewData Dictionary

In ASP.NET MVC the essence of a request isexecuting an action. The details of the action are contained in the URL in apurely RESTful manner. Any HTTP request ends with the execution of a methoddefined on a controller class. A controller class inherits from the System.Web.Mvc.Controllerclass which, in turn, inherits from ControllerBase. In ControllerBase, you'llfind a property named ViewData, which is defined as:

public abstract class ControllerBase : MarshalByRefObject,IController

{

:

public ViewDataDictionary ViewData { get;set; }

}

The ViewData property represents a built-in container usedfor passing data between a controller and a view. The property is of typeViewDataDictionary, namely a plain .NET class that implements the IDictionaryinterface and looks and behaves like a classic name/value pair, enumerabledictionary.

.

public class ViewDataDictionary : IDictionary,

ICollection>,

IEnumerable>,

IEnumerable

{

:

}

It's not by mere chance that the ViewData property is definedon the ControllerBase class and, as such, is available to any custom controlleryou may have. The idea is that once the controller has executed a given action,it gets any significant results to be shown to the user and packs it into theViewData container. The following code snippet, which you get with any ASP.NETMVC project template, shows the process:

public class HomeController : Controller

{

public ActionResultIndex()

{

this.ViewData["Message"]= "Welcome to ASP.NET MVC!";

return this.View();

}

public ActionResultAbout()

{

return this.View();

}

}

Any controller's method performs its own task,stuffs return values into the ViewData dictionary, then triggers the processthat generates an updated response for the user. Generating an updated responseis a step that involves the view engine and is triggered via one of theoverloaded View functions.

The ViewData dictionary is definitely the object thatcontains the representation of the view-model the data being worked on in theview.

How ViewData Flows Into the View

In ASP.NET MVC, the view actor is symbolized by anHTML page. With the expression "generating the view," one typically refersto the process that takes a layout (i.e., an HTML template) and some data(i.e., the content of ViewData) and produces a response for the browser. Shapeand color of the view's layout depends on the currently selected view engine.

The view engine is a pluggable component of theASP.NET MVC runtime environment that assembles together layout and data toproduce a response mostly HTML. The default view engine requires that thelayout has the form of an ASPX file. It uses the markup information there asthe HTML template to fill with data in the ViewData dictionary. Other viewengines, though, may support a different syntax for the layout.

The view engine is triggered by the View function onthe Controller class. There are quite a few distinct overloads of the Viewfunction. Here's the source code of the most configurable of all:

protected internal virtual ViewResult View(string viewName,string masterName, object model)

{

if (model != null)

{

base.ViewData.Model = model;

}

ViewResult result = newViewResult();

result.ViewName =viewName;

result.MasterName = masterName;

result.ViewData = base.ViewData;

result.TempData = base.TempData;

return result;

}

As you can see, the content of the ViewData is copied intothe ViewResult object and makes its way to the ASP.NET MVC runtime shell wherethe request is processed. The runtime uses the ViewResult object to retrievethe active view engine and make it work.

Anything Better Than a Dictionary?

A dictionary is a plain collection of name/valuepairs with perhaps some additional capabilities such as sorting and filtering.Any data you store in a dictionary is treated as an object and requires castingand boxing to be worked on. A dictionary is definitely not something you wouldcall strongly typed. At the same time, a dictionary is straightforward to useand works well.

A while back, when I introduced theViewDataDictionary class, a small but important detail passed somewhatunnoticed. With all stock dictionary classes available in the .NET Framework,why did the development team assemble yet another dictionary class?

The ViewDataDictionary is unique because it alsofeatures a Model property, as shown below:

public class ViewDataDictionary : IDictionary,

ICollection>,

IEnumerable>,

IEnumerable

{

public object Model {get; set; }

:

}

The Model property is an alternative and object-oriented wayof passing data to the view object. Instead of fitting flat data into adictionary, you can shape a custom object that faithfully represents the datathe view expects. In other words, the Model property just represents yourchance of creating a view-model object that is unique for each view. If youintend to support the Model property, you have to make it clear by deriving thecode-behind class of the view class (in the standard Web Forms based viewengine):

public partial class YourPage : ViewPage

{

:

}

If you don't use a code-behind class, you achieve thesame goal with the following page directive in the view source file:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage"%>

Figure 3 shows the dialog box that in Visual Studio 2008helps you add a view with a strongly typed model attached.

Figure 3: Adding a new view to an ASP.NET MVC project in Visual Studio 2008

Design Considerations

The MVC pattern is quite loose about a number ofimplementation aspects, including how data should be passed down to the viewengine. The web variation of MVC we're considering here doesn't mandate aspecific format either. A dictionary like ViewData is therefore an excellentsolution because it's flexible enough to accommodate any number of values ofany type. Unfortunately, a dictionary is a generic container of System.Objectcomponents. The ViewData dictionary is good enough for quick-and-dirty orshort-lived sites; it becomes rather inadequate as the complexity of the view(and the number of views) grows beyond a threshold.

When you start having tens of distinct values topass on to a view, the same flexibility that allows you to quickly add a newentry, or rename an existing one, becomes your worst enemy. You are left aloneto track item names and values; you get no help from IntelliSense and compilers.

The only proven way to deal with complexity insoftware is appropriate design. As far as MVC views are concerned, thedefinition of a view-model object for each view helps tracking and settingexactly what's really needed by the view. The definition of the view modelclass is entirely up to you. However, the ASP.NET MVC framework providesfacilities and is designed around the idea that you might be using a view-modelobject.

I suggest you define a class for each view you add,choosing an appropriate naming convention to avoid duplicates and achievereadability. I use a combination of controller and view names. For example, theview-model object for a view invoked by method Index on Home controller isnamed HomeIndexViewModel. The template for a controller method becomes thefollowing:

public ActionResult Index()

{

// Perform therequested task and get any necessary data

object data =

// Pack data for theview

SamplesIndexViewModelmodel = new SamplesIndexViewModel();

PopulateModel(model,data);

// Stores the viewmodelobject into the transfer dictionary

ViewData.Model = model;

// Trigger the view

return View();

}

You first retrieve any data to pass. Next, you create aninstance of the view-model class and copy any raw data into its set ofproperties tailor-made for the view elements. The final step is passing data tothe view. This can be done in either of two ways. Typically, you copy theview-model instance into the Model property of the ViewData. As an alternative,you pass the view-model object as an argument to the View function:

return View("index", model);

In the view markup, you retrieve the view-model object usingthe this.ViewData.Model expression. However, a convenience property also existson the ViewPage class that reduces the expression to just this.Model.

The Beauty of MVC

The beauty of MVC is that the controller of theaction does its own work and then yields to a distinct object to update theuser interface. The beauty of the MVC implementation in ASP.NET MVC is that theview object doesn't have to retrieve fresh data itself, but receives itdirectly from the controller. This article discussed two ways of packaging datafor the view using a dictionary or using a strongly typed custom object.

Dino Esposito is anarchitect at IDesign and specializes mainly in ASP.NET, AJAX and RIA solutions.Dino co-authored the best-seller Microsoft.NET: Architecting Applications for the Enterprise (Microsoft Press, 2008)and the just-released twin book MicrosoftASP.NET and AJAX: Architecting Web Applications (Microsoft Press, 2009).

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like