Skip to Navigation or
Skip to Content

Understanding MVC Means Less Brittle Code

Feeds

RSS Feed

<< June | July | August >>

Friday, 30th July 2010

I was asked a question about ASP.NET MVC today, which suggested that while people are loving it, they don't quite understand the concepts. Thanks to the awesome framework Microsoft released for ASP.NET MVC, it's very difficult not to follow the pattern reasonably well, but there are some subtle errors creeping into MVC applications.

Using the default layout that comes out of the box, you have a folder for Models, one for Views and one for Controllers. This should remind MVC developers that there are three very important and very separate roles being performed.

Model

The model should represent the data required by the view. That's all it should be. No logic, no display, nothing but a series of items that the view wants to display. Ideally, you should think of this model as supporting "some view", in that the view should be able to be changed entirely without any changes needed to the model.

View

The view is solely concerned with displaying the data contained in the model to the user. It should be the only thing that knows or cares about whether the data is displayed in a paragraph, drop down list, hyperlink or any other element. It should be possible for the view to change its mind about how things are displayed without affecting the model or the controller.

Controller

The controller deals with processing any logic that is required to get the data into the model. It performs validation, aggregation of data and all the clever bits and pieces that are needed to end up with a nice clean model full of data, which gets passed to the view. If something clever happens, it should be here. There shouldn't be anything in the controller that is specific to how the data is displayed.

Example

So now I have finished teaching you to such eggs, here is a common example of where things go wrong... drop down lists.

To display a drop down list using a HTML helper, you need to pass in a SelectList, which is a list of SelectListItem objects. The HTML helper loops through the SelectList and creates all of the options for the drop down list, and will even select the current item for you. Great.

So this is how many people make it happen... (please bear in mind that the model, view and controller are three different code files)

// model
public SelectList PaymentOptions { get; set; }
// view
<%= Html.DropDownListFor(model => model.SelectedPaymentOption, Model.PaymentOptions) %></label>
// controller
model.PaymentOptions = new SelectList(paymentOptionList, "id", "name", model.SelectedPaymentOption);

So what is wrong with this? Well, quite a lot. The SelectList (and indeed the items contained within it) are incredibly specific to the view. By putting them inside of the model and/or controller, you have tied all three to the specific concept of displaying a drop down list. If the view decides to display the items as a list of links, or a menu, or some giant buttons - you have to change the model, view and controller to make it work. This is an example of brittle code that isn't very adaptive to change.

Instead of doing that, imagine doing this instead...

// model
public IEnumerable<PaymentOption> PaymentOptions { get; set; }
// view
<%= Html.DropDownListFor(model => model.SelectedPaymentOption, new SelectList(Model.PaymentOptions, "id", "name", model.SelectedPaymentoption)) %></label>
// controller
model.PaymentOptions = paymentOptionList;

By doing things this way, you can decide to display the payment options in whatever way you wish, without any changes to the model or controller. The view can change in isolation and you don't cause a chain of changes to occur throughout the application. Isn't that better? Of course it is.

This highlights the need for ASP.NET MVC developers to constantly remind themselves of the MVC pattern and what the model, view and controller should and shouldn't do.

 

You Are Here: Home » Blog » Understanding MVC Means Less Brittle Code

 

I use a cookie on this website. This cookie doesn't contain or relate to any personal information and it isn't shared with any other website, it just ensures that I don't count you more than once in my website statistics. The Privacy and Electronic Communications Regulations require me to ask your permission to use this cookie, so please indicate below that you are happy for me to do this - I will remember your selection with a cookie, so if you accept I won't ask again...