MVC: I'll need a little bit more context on that
ScottGu recently announced the plans for the next public preview of the ASP.NET MVC framework. For those who don't feel like clicking on links to other peoples' blog posts Scott's blog says it's being released at MIX08, which is only a couple of weeks away. And yes, I will be there!
My previous blog post talked in general about the design philosophy of the ASP.NET MVC framework. Today I'd like to talk specifically about context objects, how we use them in ASP.NET MVC, and why we like them. In the coming release of MVC there will be about seven context types throughout ASP.NET, URL routing, and MVC.
What is a Context Object?
A context object is exactly that: An object that gives another object some information about what's going on. Information such as what is the current request, what task is being performed, and sometimes even the ability the change what's going on.
Context in MVC
One context object many ASP.NET developers are already familiar with is HttpContext. HttpContext gives you everything you need to know about the current request, who's making that request, and how to respond to the request. Of course, in MVC we decoupled the MVC framework from the test-unfriendly HttpContext by introducing an IHttpContext interface (which, by the way, is now an HttpContextBase abstract base class for future-proofing purposes).
However, as the request gets processed we create and gather up additional information about what's going on. The first context we add is at the routing level: the RequestContext type. It adds just one piece of information, the RouteData, as well as including all previous context information, which is just the HttpContextBase.
Once a route is selected and we determine that it is an MVC request, we're off to the controller. This is where the ControllerContext comes in to the picture. ControllerContext derives from RequestContext and adds the controller instance to it. We then have a ViewContext type, which adds information about the selected view, its view data, and some other items.
One of the new features in the upcoming preview is action filters, and sure enough there are three filter context types as well.
Since the context types derive from one another (except for HttpContextBase), you can often pass in whatever context type you have to call some method from a lower level. For example, in the view you get a ViewContext that you can pass into the URL routing methods.
What Can Context Do For You?
By passing around context objects we have no need for global state. Global state would be something like a static property or field that everyone can get to. One of the typical requirements of a unit test is that during their execution they do not consume global state nor do they alter global state. We give you the context object and it has everything you need to know. How do I know that it's everything you need to know? Quite simply, the context object is all we know anyway, so we're just letting you know about it as well.
Since your code now makes its decisions and operates on a passed-in context object, your unit tests can produce fake contexts and pass those in to your methods to see how the code reacts to them. You no longer have to worry about your code depending on global state since there simply isn't any (at least none that we create).
Have I given you enough context on what we're doing?