We are all familiar with the basic HomeController in the default ASP.NET MVC project. We know we can pass values from the controller to the view. Sometimes we are tempted to pass the controller itself to the view so that we can call methods on it. The view should not have to depend on the controller. This post provides a way to accomplish this. For more on ASP.NET MVC, check out my book, ASP.NET MVC 3 in Action. You can also check out the MVC Boot Camp training we offer at Headspring. We start with the HomeController.
We know from just a little reading that the ViewBag property on HomeController is a dynamic object – using the new .Net 4 dynamic capabilities. Merely setting the Message property on the object creates the property. It is not completely obvious how to create a new method on the object, though.
If I were to want to use a method in my Razor view like this. . .
. . . then I would need to figure out how to get the GetCurrentTime() method onto the ViewBag. The following is the solution to that problem.
There are two technical capabilities of C# 4 that provide the ability to accomplish our new method. The first is that I can create and set any new property on the dynamic object. The second is actually a feature of .Net 2 – delegates. I will create a method and then wrap it in a delegate and assign it as a property of ViewBag.
.Net 3.5 brought us the Func<> and the lambda expressions. These make delegates so much more concise to write and read. I have now create a method, assigned it to a object and set it as a property on ViewBag.
The only thing left to do is to dereference the property and invoke it with ().
For those of you who have been programming for a while, you know that I technically haven’t create a method on the ViewBag object. That is correct. We have to think back to why I asked for the method in the first place.
Why do we need methods?
We need methods in order to retrieve values that are resolved at run time. For instance, if I need to pass in some view-specific value to my ViewBag for evaluation, I need a method. If you were ever tempted to pass a reference to the controller to the view just to be able to execute a method on a value the controller owned, this is your ticket to accomplishing that. Because the method/closure/delegate in the controller has full scope access to the controller memory space, the ViewBag now holds the gateway to the controller’s state that is necessary.