SingingEels : Development Community & Resource

Login

Articles

  • ADO.NET (2)
  • ASP.NET (36)
  • LINQ (5)
  • Security (2)
  • Silverlight (3)
  • SQL (7)
  • Standards (5)
  • WCF (2)

Syndication

  • Articles RSS
  • Blogs RSS

Contribute

  • Our Authors List
  • Member Sign-Up
  • Suggestions Box

How to Handle "Side Content" in ASP.NET MVC

(Aug 14 2008 - 07:32:38 AM by Timothy Khouri) - [print blog post]

A couple of days ago, Stephen Walther made a great post (ASP.NET MVC Tip #31 – Passing Data to Master Pages and User Controls) on a subject that is bound to come up 100 times more until MVC is fully understood. This post is a follow-up to that one, in hopes to have a clear sense of what to do with the issue.

The issue is as follows: MVC is rests on the pillars of 1) Testability and 2) Single Responsibility. Every function (action, page, whatever you want to call it) should be fully testable, and it should only handle one point of concern. So the question is, how do we handle supplemental data?

Our Scenario

Imagine if you built an MVC web application for a car dealership that had the following actions (or pages):

  • Home - ContactUs
  • Home - OurLocations
  • Vehicles - ListCars
  • Vehicles - ViewCarDetail

At first glance, this would be very straight forward and very easy to solve (and it is). I would make a "HomeController" and have the ContactUs and OurLocations actions there, and I would make a "VehiclesController" and put the ListCars and ViewCarDetail actions there. So Where's the Problem?

A Slightly More Complex Page

Imagine, though, if you didn't just want to list all the cars on the "ListCars" page. What would you do if you wanted to also show the "Top 5 Custom Testimonials" in a <div> on the right side of the page. You want to have that shown on both of the 'vehicles' pages (ListCars and ViewCarDetail).

So the question comes in... "Who's responsibility is it to retrieve that data from the data store?" Would you add that code to each function?

public ActionResult ListCars()
{
   GetTestimonials();

   // Now do the ListCars stuff???

}

public ActionResult ViewCarDetail()
{
   GetTestimonials();

   // Now do the ViewCarDetail stuff???

}

You would *NEVER* want to do the above as that is a 100% violation of one of the pillars of MVC (the Single Responsibility Principle). Not to mention that you're working harder than you have to.

Would you make a custom ActionFilter and decorate your methods?

[TestimonialGetter]
public ActionResult ListCars()
{
   // Now do the ListCars stuf???

}

[TestimonialGetter]
public ActionResult ViewCarDetail()
{
   // Now do the ViewCarDetail stuf???

}

That's hideous, and is simply putting a new dress on an old wench. So then, what do we do?

Look At the Data for What It Is

The problem here is that we're losing focus of what the data really is. That supplemental data is not the main focus of the "View", and it's throwing us off. If we didn't have that "Top 5 Testimonials" stuff, we wouldn't have a problem.

To prove my point, imagine if we didn't want to show "Top 5 Testimonials", but instead we wanted to show... let's say... the logged in user's name! Would that be so hard?

"That's easy", you say, "all I have to do is <%= User.Identity.Name %>". True, that is easy. But did you notice that we're not freaking out about the fact that we just got some "data" from a "data base" and displayed it in our View :)

The same is true for other, non-view-specific data. So, to solve our issue above, we would most-likely create a base class for our Vehicles controller that got that extra data (in the constructor) and put the needed info into the ViewData collection.

Is that testable? Does that allow a single responsibililty? Yes, it is and yes it does. In your testing framework, you would mock up the data store, and then you could test each action to make sure that it has all the data (including the Top 5 Testimonials stuff).

Important Conclusion

MVC is a great design pattern, and it's been around for a long time. However, ASP.NET MVC is new, and there will likely be many revisions and redefinitions to how it will address issues like this. But as long as you keep to the guidelines of MVC then you will be able to reap it's benefits.

  • Aug 14 2008 - 09:53:50 AM pvencill

    Timothy,

    This is a great post. I read the one on Stephen's site yesterday, and I think your solution is perfect and precise. It's so obvious that folks don't realize it, and make the problem harder than it needs to be.

    I was thinking of something similar, having the controller assemble a ViewModel sort of affair; I think what's making most folks choke is the assumption that "SRP" translates into a Controller only dealing with one model entity, which I don't think is necessarily the case.

    The only downside I can see to the comparison, is that the User object in this case is really a property of the Page class, which is legacy from WebForms. I don't know that that property would be appropriate in a true MVC app; instead I'd expect the data contract between the Controller and the View (the ViewData Model or ViewModel depending on your upbringing) would hold that information, as you suggested in your second to last sentence in the Look At section.

You must be logged in to add comments. If you have not already done so, you can create an account here. If you already are a member, you first need to login before you can comment.

Developer / Architect / Author
SingingEels.com as of Jul 04 2009 - 09:59:12 AM - (0.0625096)