Channels ▼
RSS

Design

Using ASP.NET's ActionResult to Abstract Dependencies


The authors are also authors of ASP.NET MVC 2 in Action


While the MVC Framework gives you a lot of control for using the framework and creating controllers, there are still some features of ASP.NET that are difficult to simulate in a test. By taking that difficult-to-test code out of an action and putting it into the Execute method of an action result, the actions become significantly easier to unit test. The reason for this is that when you unit-test an action, you assert the type of the action result that the action returns and the state of the action result. The execute method of the action result is not executed as part of the unit test.

Listing 1 shows how moving the FormsAuthentication.SignOut() call from an action and into the action result abstracts that line of code and prevents it from executing from within the action method.

 
public class LogoutActionResult : ActionResult { 
    public RedirectToRouteResult ActionAfterLogout { get; set; }                <b>A </b>
    public LogoutActionResult(RedirectToRouteResult actionAfterLogout) <b> B </b>
    { 
          ActionAfterLogout = actionAfterLogout                                               <b>B </b>
    } 
    public override void ExecuteResult(ControllerContext context)
         FormsAuthentication.SignOut();                                                             <b>C </b>
         ActionAfterLogout.ExecuteResult(context);                                           <b>D </b>
    }
 }

<b>
A           RedirectToRouteResult is testable<br>
B           Constructor sets ActionAfterLogout<br>
C           SignOut is hard to test <br>
D          ActionAfterLogout result is executed. </b>

Listing 1: Moving hard to test code into an ActionResult

This allows an action to return a LogoutActionResult. The testing of that method does not have to deal with calls to the FormsAuthentication class. The test can just assert that the LogoutActionResult was returned from the action. The test can also assert the values in the RedirectToRouteResult to make sure that the action correctly setup the redirect.

Listing 2 shows that the Logout action method returns the new LogoutActionResult method.


public ActionResult Logout() 
{ 
      return new LogoutActionResult(RedirectToAction("Index","Home")); A 
} 

<b>A           The testable Logout action method </b>

Listing 2: Action method that uses the LogoutActionResult

The constructor parameter to the LogoutActionResult is a RedirectToAction result that will redirect the browser to the Index action on the HomeController.

Summary

The advanced controller extensibility in MVC 2 allows you to tweak the framework easily. The IController interface allows the most control, but the various controller base classes provide some very useful but flexible capabilities. Actions help you easily break down basic functions of a single controller. Action filters provide hooks for inserting code before or after action execution. Action selectors help you provide hints to the action invoker about which action should be selected for execution, and action results help to encapsulate repetitive rendering logic.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video