Delegating Action Result

In my last post, I walked through a simple example of an ActionResult that you can use to transmit a file to the user’s browser along with a download prompt.

The MVC framework will include several useful action results for common tasks. However, we might not cover all results you might want to return. In this post, I walk through a simple result that will cover all remaining cases. With the DelegatingResult, you simply pass it a delegate. This provides ultimate control. Let’s see it in action.

public ActionResult Hello() {
  return new DelegatingResult(context => {
    context.HttpContext.Response.AddHeader("something", "something");
    context.HttpContext.Response.Write("Hello World!");
  });
}

Notice that we pass in a lambda to the constructor of the action result. This lambda is a delegate of type Action<ControllerContext>. By doing this, the lines of code within that block (Response.AddHeader and Response.Write) are deferred till later.

Here’s the code for this action result.

public class DelegatingResult : ActionResult {
    
  public Action<ControllerContext> Command {
    get;
    private set;
  }
    
  public DelegatingResult(Action<ControllerContext> command) {
    this.Command = command;
  }

  public override void ExecuteResult(ControllerContext context) {
    if (context == null) {
      throw new ArgumentNullException("context");
    }
        
    Command(context);
  }
}

I updated the sample I wrote in my last post to include this demo. Download the source.

Technorati Tags: ,,
[ad] Free Bug Tracking & Project Management Software Axosoft’s OnTime 2007 allows software development teams to collaborate on software projects by tracking everything from defects to enhancements to helpdesk incidents in one easy-to-use database driven by an intuitive Windows, Web or VS.NET Integrated UI. Get a Free Single-User License ($200 Value!)

What others have said

Requesting Gravatar... Andrew Davey May 11, 2008 9:50 AM
# re: Delegating Action Result
How about having a ComposedActionResult as well?

return new ComposedActionResult(
RenderCookie("uid","123")
RenderHeader("foo","bar"),
RenderView("Index")
)
Requesting Gravatar... Andrew Davey May 11, 2008 1:29 PM
# re: Delegating Action Result
Thinking about composition led me to...

What about going back to having controller actions returning void?

The difference being that the RenderView method only queues on operation in the controller. This queue can be played back by the MVC framework to generate output later. It can still be tested easily as well. Just expose an ResultOperations property for example.

The controller methods will look cleaner without the "ActionResult" type and the "return". This is good! "return RenderBlah(...);" doesn't read very well IMO.

P.S. An extra piece of testing syntax magic. The above technique allows for: Assert.That(controller.DidRenderView("Index"))
By using an extension method that looks at the ResultOperations queue. :D
Requesting Gravatar... Steve May 11, 2008 4:44 PM
# re: Delegating Action Result
Andrew,

I wonder why they don't just provide both.

Either way, I'm happy with MS MVC :)
Requesting Gravatar... Dragan Panjkov May 11, 2008 5:39 PM
# re: Delegating Action Result
Even with this release I keep receiving error regarding assembly not signed or something like that...
Could not load file or assembly 'System.Web.Mvc' or one of its dependencies. Strong name signature could not be verified. The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT: 0x80131045)
Requesting Gravatar... Dragan Panjkov May 11, 2008 5:48 PM
# re: Delegating Action Result
here are steps I am using to test this on pre-preview 3 build
1. I create mvc project using vs template (pre-preview3) and run it to be sure it is working
2. add actionresultlibrary project to the solution
3. delete entire contents of bin folder in both projects
4. add references to assemblies inside reference_assemblies folder
5. build actionresultribrary and update reference to it inside mvc web app
6. build mvc web app and run it... and voila... it is working perfectly
Requesting Gravatar... Andrew Davey May 12, 2008 6:09 AM
# re: Delegating Action Result
Steve,

Whilst both options can live side-by-side. Would you really use the explicit ActionResult/return when void/no-return option is less effort?
Requesting Gravatar... Steve May 12, 2008 9:48 AM
# re: Delegating Action Result
Andrew,

It depends on my testing strategies, or if I test at all.

The framework an assist me for writing tests, that is great. But it assumes I'm writing tests
Requesting Gravatar... Haacked May 12, 2008 9:49 AM
# re: Delegating Action Result
@Dragan nice!
Requesting Gravatar... Dragan Panjkov May 12, 2008 2:37 PM
# re: Delegating Action Result
@Haacked: I have one better solution... just replace dll's in dependencies folder with those created with my visual studio MVC template... I have resolved that early in monday morning (around 3 AM) when I wanted just to try these samples :)
Requesting Gravatar... Steve May 12, 2008 8:41 PM
# re: Delegating Action Result
That worked - thanks everyone

What do you have to say?

(will show your gravatar)
Please add 2 and 2 and type the answer here: