Skip navigation

I just read Jimmy Bogard’s post on how we do MVC ViewModels and I must say, I digg the approach. Personally, I find it a shame that the ViewData dictionary is so damn prominent.

In the comments there was a little bit of discussion on how to handle the ViewModel for the master page. Since there wasn’t much of elaboration on the topic, I thought I’d mention how I’m doing it for quite a while now, and I’m still ok with it :-).

I chose to use a ViewModel base class for the master page with the following in mind:

  • The base class only contains information that makes sense for every view page that is using the particular master page.
  • Just like Jimmy explains in his post, I also have very specific requirements. I’m not only talking about XHTML et. al., but things like unique titles, etc.
  • I’ve got my app split up in independent modules. The only thing they’ve got in common, is a base class for initialization and the fact that their views reside in the same project/directory structure on disk. This means that when I’m working in module X, I know what my master page and its (ViewModel-) requirements are and can subclass ViewModel as I see fit.

Before I continue: I certainly do not put ALL view model data of the master page in the base class, don’t get me wrong. There is quite some information that’s rendered by the master page, but that information is not coming from its model. Most things come from composed RenderActions (not partials!). Only view data that can be/needs to be provided by distinct action methods is defined in the base class. Every master page in my app (typically, one per module) inherits from ViewMasterPage<ViewModel> where ViewModel looks something like this:

/// <summary>

/// Represents the model that contains information for the view.
/// </summary>
public class ViewModel
{
	private readonly HtmlHeader header = new HtmlHeader();

	/// <summary>
	/// Represents the information for the (X)HTML head element.
	/// </summary>
	public HtmlHeader HtmlHeader { get { return header; } }
}

I guess it’s no surprise that to you that HtmlHeader looks like this (in my case):

public class HtmlHeader
{
	public string Title { get; set; }
	public string MetaDescription { get; set; }
	public string MetaKeywords { get; set; }
}

My master page itself uses the ViewModel as follows:

...
<head>
	<title><%= Html.Encode(Model.HtmlHeader.Title ?? Resources.Master.DefaultPageTitle) %></title>
	<meta name="description" content="<%= Html.Encode(Model.HtmlHeader.MetaDescription ?? Resources.Master.DefaultMetaDescription) %>" />

	<meta name="keywords" content="<%= Html.Encode(Model.HtmlHeader.MetaKeywords ?? Resources.Master.DefaultMetaKeywords) %>" />
	...
</head>
...

This model only contains information that is to be supplied by action methods. When an end user requests product information, the action method must provide the title, META keywords etc. When a user requests a content page, the ViewContent(string slug) method is responsible for getting the content and map its title, META description, author, copyright, etc. to the ContentViewModel.

But how can we be sure?

Ok so far so good, we’ve organized ourselves a bit, but how can we make sure we return the proper type of view model? Due to the loose coupling between the M, V and C and the way ControllerBase and Controller are designed, it practically requires a rewrite (encapsulation if we’re lucky) of the existing hierarchy…

But then again, if you’re doing TDD, you should be fine (’the_view_model_should_…’). If you’re not, the very first HTTP GET will blow up, so you’ll know something’s wrong soon enough either way. So, why go through all this hassle?

This does not mean there’s nothing that can’t be done! But before I (try to) do, I’m going to address my SRP issue! I currently investigating things like commands in stead of controllers and ActionControllers and how to fit in the ViewModel (maybe).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: