Sunday, June 3, 2012

Thoughts on ActionResults

ActionResults are a good way to make your controllers more testable.  For example, HttpContext.Current  is not available in unit tests a null reference exception occurs when testing code that calls HttpContext.Redirect, however because the Redirect ActionResult is returned and not executed by the controller unittests can check the action returned and ensure that it is a redirect without needing to mock an entire HttpContext.

Note: While MVC does wrap HttpContext which allows you to mock it while testing, it’s a lot easier if you don’t have to deal with it at all.

A similar approach can be used for LogIn/LogOut, you could abstract the FormsAuth call to a custom service but again you would need to pass a mock in your tests or risk another null reference, using a ActionResult instead makes testing much easier

File Result
They also are a great method of code reuse. You would never imagine of putting the code that reads a view and renders it in every action, so why add the code that outputs a pdf/ical/rss/xls/graph/report inline in the controller?  Simply return a Result that knows how to render the pdf and pass the data to it.

Status Results 
You can use the decorator pattern to extend what a view does.  I like adding a status message at the top of a page after an action has taken place eg “User created successfully”.  Instead of adding extra properties to every ViewModel to include a status message, I just put the message into TempData (Not ViewBag as that won’t live through a redirect) and consume it in the view.

I then use an extension method to make it a bit nicer to use

Unit tests can then check that a StatusResult is returned that contains another action which performs the redirect.