Enabling IoC in ASP.NET ActionResults (or, a better ActionResult)

One of the more interesting abstractions in ASP.NET MVC is the concept of an action result.  Instead of calling a method to direct the result of calling an action, such as frameworks like Rails allows:

   def create
      @book = Book.new(params[:book])
      if @book.save
            redirect_to :action => 'list'
      else
            @subjects = Subject.find(:all)
            render :action => 'new'
      end
   end

Instead, the return value of an action directs the MVC pipeline on what to do next:

public ActionResult Index()
{
    ViewData["Message"] = "Welcome to ASP.NET MVC!";

    return View();
}

Instead of displaying the view when the View method is called, the command to render a view is packaged up into a ViewResult object, containing all of the information needed to render a view.  This is the basic command pattern, and each derived ActionResult is a different command.  There are quite a few subclasses of ActionResult, each representing a different command for the MVC pipeline:

  • JsonResult
  • ViewResult
  • RedirectResult
  • FileResult
  • etc

If you want custom processing of the result of an action, a custom ActionResult is what you’re looking for.  We have quite a few in our applications, including:

  • Streaming a CSV version of the current screen
  • Executing a domain command
  • Executing a delete

And a few more.  While the abstraction of a parameter object to represent a command is a fantastic idea, the design of the ActionResult type is hindered by too many responsibilities.  Namely, an ActionResult is responsible for:

  • Representing the parameter object of a command
  • Executing the command

It’s that second responsibility that can hinder some more interesting scenarios.  Because the controller action needs to instantiate a parameter object as the result of an action, I’m often reduced to sub-optimal service location to do the actual work of the executing action.  For example, the delete action result might look something like:

public class DeleteRequestResult<TModel> : ActionResult
{
    private readonly TModel _model;
    private readonly Func<ActionResult> _successRedirect;

    public DeleteRequestResult(TModel model, Func<ActionResult> successRedirect)
    {
        _model = model;
        _successRedirect = successRedirect;
    }

    public TModel Model { get { return _model; } }
    public Func<ActionResult> SuccessRedirect { get { return _successRedirect; } }
    
    public override void ExecuteResult(ControllerContext context)
    {
        // Service location, boooooo!
        var repository = IoC.GetInstance<IRepository<TModel>>();
        var logger = IoC.GetInstance<IDomainLogger>();

        repository.Delete(Model);
        logger.LogDelete(Model);

        var redirectResult = SuccessRedirect();

        redirectResult.ExecuteResult(context);
    }
}

I have to resort to service location (blech) to load up the right dependencies to do the actual work of processing a delete request.  However, instead of relying on the ActionResult to be responsible for executing the command, I’ll instead allow something else take over that responsibility.

Separating the ActionResult concerns

First, I need to define an abstraction of something that can execute an ActionResult.  That sounds like an IActionResultInvoker to me:

public interface IActionResultInvoker<TActionResult>
    where TActionResult : ActionResult
{
    void ExecuteResult(TActionResult actionResult, ControllerContext context);
}

The signature is very similar to ActionResult, but this time, it’s a separate object that receives the parameter object (the ActionResult), the ControllerContext, and actually performs the work.  Next, I need to now direct the default action invoker to invoke action results through my abstraction, instead of going through the regular action result itself.  However, because all of the built-in action results aren’t going to change, I need to handle that scenario.  To accomplish this, I’ll create a new ActionResult type:

public abstract class BetterActionResult : ActionResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        throw new NotImplementedException("Should be executed with an IActionResultInvoker");
    }
}

That should be enough to provide some notification when we’re developing if we haven’t hooked things up correctly.  Next, I’ll need the default action invoker overrides:

public class IoCActionInvoker : ControllerActionInvoker
{
    private readonly IContainer _container;

    public IoCActionInvoker(IContainer container)
    {
        _container = container;
    }

    protected override void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
    {
        if (actionResult is BetterActionResult)
        {
            // Close the IActionResultInvoker<> open generic type
            var actionResultInvokerType = typeof (IActionResultInvoker<>).MakeGenericType(actionResult.GetType());

            // Get the invoker from the container
            var actionResultInvoker = _container.GetInstance(actionResultInvokerType);

            // Get the generic ExecuteResult method
            var executeResultMethod = actionResultInvokerType.GetMethod("ExecuteResult");

            // Call the ExecuteResult method
            executeResultMethod.Invoke(actionResultInvoker, new object[] { actionResult, controllerContext });
        }
        else
        {
            base.InvokeActionResult(controllerContext, actionResult);
        }
    }
}

It’s a lot of code, but what I’m basically doing here is looking for derived BetterActionResult action results, and using my StructureMap container to load up the correct IActionResultInvoker for that derived ActionResult type.  In the example above, I use just basic reflection for calling the ExecuteResult method, but in practice, I’ll use caching and an optimized mechanism for reflection.

Connecting the action invoker to the MVC pipeline

Now, I could have used a looser-typed signature for IActionResultInvoker, and not needed to do this reflection business.  However, it’s critical that I load up the correct IActionResultInvoker for my derived BetterActionResult.  Using generics is a great way to use the type system for routing to the correct handler.  To replace the existing action invoker, I have a couple of choices.  One simple way of doing so is to modify the controller factory (that I’m already overriding for using IoC to instantiate my controllers):

public class ControllerFactory : DefaultControllerFactory
{
    private readonly IContainer _container;

    public ControllerFactory(IContainer container)
    {
        _container = container;
    }

    protected override IController GetControllerInstance(Type controllerType)
    {
        if (controllerType == null)
            return null;

        var controller = (Controller)_container.GetInstance(controllerType);

        controller.ActionInvoker = _container.GetInstance<IoCActionInvoker>();

        return controller;
    }
}

My custom controller factory is already hooked up using a technique like this one, I don’t have to do anything extra to make sure my action invoker gets executed.  I just overrode the method I needed, hooked up the action invoker on controller construction time, and I’m ready to go.

The next piece is to actually define my custom action invoker, and refactor my existing DeleteRequestResult type.

Defining a new invoker and action result

First, I’ll need a new ActionResult type for my original representation of a delete request.  This time, I’ll only have the parameters needed to perform the action, and my action invoker will take care of the rest.  The custom action result type now becomes very simple:

public class DeleteRequestResult<TModel> : BetterActionResult
{
    public DeleteRequestResult(TModel model, Func<ActionResult> successRedirect)
    {
        Model = model;
        SuccessRedirect = successRedirect;
    }

    public TModel Model { get; private set; }
    public Func<ActionResult> SuccessRedirect { get; private set; }
}

I’m no longer mixing the concerns of parameter object and command execution any more.  Instead, I’ll define a new custom action invoker:

public class DeleteRequestResultInvoker<TModel> 
    : IActionResultInvoker<DeleteRequestResult<TModel>>
{
    private readonly IRepository<TModel> _repository;
    private readonly IDomainLogger _logger;

    public DeleteRequestResultInvoker(IRepository<TModel> repository, IDomainLogger logger)
    {
        _repository = repository;
        _logger = logger;
    }

    public void ExecuteResult(DeleteRequestResult<TModel> actionResult, ControllerContext context)
    {
        _repository.Delete(actionResult.Model);
        _logger.LogDelete(actionResult.Model);

        var redirectResult = actionResult.SuccessRedirect();

        redirectResult.ExecuteResult(context);
    }
}

Now, when my IoCActionInvoker looks for an action invoker for DeleteRequestResult<TModel>, it will find my custom action invoker, instantiate it with IoC, and use its ExecuteResult method.  The controller action becomes pretty small now:

public DeleteRequestResult<Product> Delete(Product productId)
{
    return new DeleteRequestResult<Product>(productId, () => RedirectToAction("Index"));
}

When I go to test this action now, I only need to make sure that the product supplied is correct and the success redirect is correct.  Because deletions don’t really change in our domain, we abstracted deletions into a separate ActionResult and IActionResultInvoker.

Wrapping it up

The piece I didn’t show here is how to hook up your IoC container to tell it that when it looks for an IActionResultInvoker<DeleteRequestResult<TModel>>, it loads up the DeleteRequestResultInvoker<TModel>.  That code is different for every container, so I’ll go into that piece in a future post.

The interesting part about this pattern is that I’m able to separate the concerns of a parameter object representing the results of an action, and the actual processing of that parameter object.  These two concerns usually have different reasons for change, and I’d rather not rely on things like service location for opaque dependency resolution in the execution of the ActionResult.  Because our IoC registration discovers new invokers quite easily, I never really need to add any new code for new action result invokers.  I merely need to create a new BetterActionResult type, define an invoker, and my IoC container does the rest.

The custom ActionResult made it easy to represent common execution patterns, in a way that doesn’t pollute my controllers with duplication and enables much easier testing.  Just as I don’t test a ViewResult for the contents of a view, in my example, I just make sure the custom ActionResult gets the correct parameters.  While many areas in MVC are designed for IoC scenarios in mind, others are not.  However, with some creative changes, we can enable places like ActionResult execution pipeline for powerful IoC scenarios.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in ASP.NET MVC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Dan Malcolm

    Yeah, we definitely need a good infrastructure to move logic out to commands and stop the code / dependency bloat that you see in contollers.

    Is our humble ActionResult the best candidate though? To me their responsibility should be restricted to the delivery of UI functionality according to the outcome of the “meat” of the controller action. They have a nice tightly focussed role and I’m just not sure if it’s a good thing to be highjacking the ActionResult execution mechanism to execute the main body of your application / business logic.

    Wouldn’t the following controller logic be cleaner?

    1. Issue a DeleteRequestCommand. This gets executed by DeleteRequestInvoker (controller has dependency on an ICommandInvoker, which finds relevant Invoker)
    2. Controller receives a DeleteRequestResult that informs us of the outcome of the operation
    3a. If result.Success then return ViewResult to render the “well done” view (or RedirectResult to get back to previous screen or something)
    3b. If not, return ViewResult to render the “sorry guys” view to display contents of result.Problems collection

    The main business logic coordination belongs in the command / invoker. The controller’s responsibility is to decide what to do in the UI according to the outcome.

    With a consistent convention for commands and their results and the following helper method in your controller base class…

    protected ActionResult ExecuteCommand[TCommand,TResult](T command, Func[TResult,ActionResult] ifSucceeds, Func[TResult,ActionResult] ifFails)

    … controller action code could probably be limited to 1 or 2 lines.

  • ZeusTheTrueGod

    I would like to see a more simple solution without command executer

    My idea is replace
    public ActionResult DeleteMethod()
    {
    //ViewData["Message"] = “Welcome to ASP.NET MVC!”;
    return new DeleteResult({ … })
    }
    with

    public ActionResult DeleteMethod()
    {
    //ViewData["Message"] = “Welcome to ASP.NET MVC!”;
    return Kernel.Resolve({…})
    }

    now we are constructing the ActionResult via Dependency Injection

    So DeleteResult can be defined as
    public class DeleteResult:ActionResult
    {
    public IMyLogger MyLogger{get;set;}
    public IMyRepository MyRepository{get;set;}

    public override void ExecuteResult(ControllerContext context)
    {
    MyLogger.DoSomething();
    MyRepository.DoSomething();
    }
    }

    I think this is a more simple way to use a dependency injection.
    Of course controller must have initialized property “public IKernel Kernel {get;set;}”, which is easy implemented when ControllerFactory is made as in the blog article – controller is obtained via IoC container.

    Because DeleteAction is created with IoC it should be registered in it with “Transient” lifestyle.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Zeus, @Dan

    Both of these solutions require a layer supertype controller with a dependency. The whole reason I moved towards something executing a parameter object (think of it as a message, and IHandler) was so that each handler could have its logic contained independent of all other handlers.

    @Dan

    We’re up to 8-9 custom ActionResult objects. Service location in each of the ExecuteResult is not acceptable. Neither is putting all of the logic down into the base controller, I don’t want layer super type dependencies, it just doesn’t scale.

    @Zeus

    That works, but it’s not an improvement. I now have more moving pieces in a controller action, making it harder to test. WIth a handler separate from the message, I can allow the structure of the message and creation of it grow orthogonal to the logic handling the message.

  • http://Http://jeffreypalermo.com Jeffrey Palermo

    This is the problem of getting a dependency from anywhere that cannot uses constructor injection. Using the normal abstract factory inside a singleton works nicely.

    Even though the dependency on the container has been technically avoided here, the code still depends on a fine-grained interface that only container can satisfy. Removing the whole notion of a container. Is what you want. Then wire up the container on the side.

    CodeCampServer has some examples of regular abstract factories

  • http://www.chaindrug.com Gilligan

    I understand the positions of both your team, Jimmy, and Dan’s comment. I think the main issue is that this is a work-around to the fact that ASP MVC does not have strong support for Controllerless Actions. If the Controller infrastructure were more focused on a controller-per-action, then much of this logic could be moved to the controllers.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Gilligan

    Yeah, at that point it’s probably a preference thing. However, I don’t ever want to add a dependency to a base controller type. If an entire family of Save actions now needs some extra thing to do its work, I don’t want to add that dependency to all derived classes. Just the difference btwn inheritance and composition.

  • Dan Malcolm

    > .. up to 8-9 custom AR objects
    Same here (stuff like PermanentRedirectResult etc), but they’re all focussed on UI outcome of action. I’m sure that this was the intention of the framework design. The OnActionExecuted hook implies that the controller has done its work and given us an ActionResult that represents the final outcome of the action in the browser (which we can safely inspect and / or modify to support things like caching model of a ViewResult, converting it to Json if it’s an ajax request etc). Does adding the role of specifying business logic that needs to be executed break this “contract”?

    > Service location in each of the ExecuteResult is not acceptable

    Yes my suggestion would involve a single dependency that would resolve the invoker for the command. There may be more elegant ways – this was just a starting point for exploring ways of invoking the command within the action method. I could just as easily have the dependency supplied to the base controller class via setter injection, which is ultimately what you’ve done. Other times it makes sense to move key cross-cutting dependencies to a static service locator (things like event bus or SystemTime wrappers) and take a small hit in your test setup code.

    You’re definitely onto something with the commands though – interesting to see how this progresses.

  • http://www.jarrettmeyer.com Jarrett Meyer

    Rails is simple because there are no dependencies – therefore no DI and no IoC. You don’t have IRepositories, because EVERYONE writing a Rails app uses the built in ActiveRecord classes. You get very small amounts of wiring up in Rails because the Rails framework does everything for you.

    .NET is just so much different. There are so many ways to communicate with a data store. In MVC, you have to do so much meta programming to do stuff that has nothing to do with solving your business problem.

  • http://blog.ploeh.dk Mark Seemann

    My first reaction to this is very similar to Dan Malcolm’s. The purpose of the Controller is to invoke the Domain Logic. The purpose of an ActionResult is to translate the result to a response stream that a browser can understand.

    While it may look like a Command object, I think that its purpose is entirely different. You can hijack it to execute Domain code, but that was never the intention.

    Keeping the Domain action in the Controller is just a lot simpler, but I’m not sure I understand how this conflicts with Controller base classes and such (but I’m totally a “favor composition over inheritance” guy myself, so I don’t have any hierarchy when it comes to Controllers).

    In any case, let’s take a look at your first attempt at DeleteRequestResult where you don’t like having to do Service Location. You are already injecting the Model and redirect action into the type, so why not also inject the repository and the logger now that you’re at it?

    Not that I would inject the logger myself, though. Having the logger there violates the SRP. Logging is a cross-cutting concern and much better handled as such. Decorators are fantastic tools for implementing AOP-like features with DI, so I would rather prefer a LoggingDecorator that decorates that real action – that’s what we do at Safewhere, and it works like a charm.