ASP.NET MVC: Don’t Fear the ViewBag

As we continue to work on our ASP.NET MVC3 project, I’m continuing to be impressed with how quick and lean the development process has gone so far.  Already, our small team is swarming and are empowered with figuring out the problems that are common at the start of a project.  One of these was a UI requirement that turned out to be an eye-opening use of one of MVC3’s more divisive features:   ViewBag.

Why the divisiveness?  Because the ViewBag is a dynamically-typed object.  If you’re a Ruby, Python, or Javascript programmer, you know all about everything being a nail.  For C# programmers comforted by a strongly-typed language, this is the type of stuff that we lose sleep on.  Properties on a dynamic object are defined at run-time, so to add a new property you just use it!  In fact, one of the first uses of this that you come across in an MVC project is the following:

	ViewBag.Title = "My Home Page";

What is “Title”?  It’s a property on the dynamic ViewBag that is defined as soon you get or set the property.  We had this in prior verisons of MVC as ViewData, but notice the difference.

ViewData["MyObj"] = myObj;
MyObject o = ViewData["Title"] as MyObject;

ViewBag.MyObj = myObj;
var o = ViewBag.MyObj;

The ViewData was object typed, so you had to always cast it when trying to get the value.  This usually lead to a mess if you abused the ViewData and ended up with casts all over the place.

Now, let me say that I feel that dynamic objects in a strongly-typed language should be treated as if they were loaded weapons:  know how to use it, use it only if necessary, and keep the safety on!  So it was the other day that we found a great use to fire our ViewBag!!

We had a UI requirement that depending on where the user was in the site, that the color of some elements would change.  This was purely view-related logic and had nothing to do with our underlying model or business logic.  We quickly brought up a few options:

  • Pass some string value via the Controller using view models
  • Pass some string value via the Controller using the ViewBag
  • Use JQuery to do some CSS toggling
  • Create an extension method when creating the object that would determine the right CSS string

None of these options “smelled” right.  I didn’t want a pure view-related item like a CSS class name in my Controller code, JQuery seemed silly, and an extension method would require compiling code if something changed.  Then, I had a quick glance at that ViewBag.Title code and it clicked!  At the top of each of our sub-layout pages, we add this line of code that specifies the CSS class to be use to customize the color of our element for all pages that derive from the sub-layout page.

    ViewBag.NavStyle = "nav_color_blue";

Then in our partial view that renders the element:

<a class="nav_global @ViewBag.NavStyle" href="@Url.Action(" Index", "Home")">home</a>

In minutes, we had our solution for this purely view-only requirement and didn’t have to clutter up code in our Controller or add silly workarounds.  This fits!  And if for some reason a page does not define the NavStyle property, it just defaults to empty string and the default color in the first CSS class.

So I have found a great use for ViewBag that doesn’t make the strongly-typed hairs on my back to raise in horror.  And you know what?  It felt gooooooood!  Yes, I will continue to make sure this dynamic object is used only if absolutely needed, but in this case we embraced the “get ‘er done” attitude and completed this requirement quickly and in a way that makes sense.  I look forward to other creative ways we can use the dynamic property to solve view-related issues and requirements.

  1. No trackbacks yet.

Leave a Reply

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

You are commenting using your 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 )

Connecting to %s

%d bloggers like this: