The MVC framework – The IActionInvoker interface
Today we’ll keep looking at the source code of the ASP.NET MVC platform. In a previous post, we’ve talked about the Controller lidycle and on what goes on when a controller is instantiated and its Execute method is called (btw, if you haven’t already, you should take a look at this post which explains why now we have a new ControllerBase class).
In this post we’re going to see how the Controller class depends on a specific IActionInvoker implementation to do the hard work that goes on when a method of your controller is executed. In the current release, you can plug your own IActionInvoker, though I believe that most of us (if not all) will want to go with the default ControllerActionInvoker class.
The InvokeAction method gets things going. It starts by finding the current action method. If it finds one, it starts by getting the parameters from the MethodInfo object and it tries to get their current values by using getting the associated ModelBinder. We will come back to model binders in a future post. For now, it’s sufficient to understand that they’re there to help the platform “understand” the submitted types (for instance, with this new type you can easily build new complex types from data submitted by a form). This is really an interesting topic which will probably “consume” more than one post, so I’ll will definitely leave it for a future post.
Ok, back to the current method invocation…after getting a dictionary with parameter names and respective values, the class will get a list of filters that have been applied to that method or type. It’s important to understand that the final filter list will be filled with attributes applied to the current method + attributes applied to the current type. It’s also important to keep in mind that all filter attributes extend the FilterAttribute base class and implement one of the following interfaces:
- IActionFilter: general purpose attribute that will let you intercept a specific action;
- IAuthorizationFilter: filter that will let you specify who can execute a specific action;
- IExceptionFilter: filter that will let you intercept and handle an exception generated by an action;
- IResultFilter: similar to the IActionFilters, but these run after the action filter have run.
In most cases, whenever you need to use one of these filters you’ll end up using one of the instances of the ActionFilterAttribute (IActionFilter and IResultFilter), AuthorizeAttribute and HandleErrorAttribute classes.
After getting all those filters, they’re added to sepcific lists so that they can be run in order. The first to run are the authorization filters. If any of those filters set the Cancel property of the AuthorizationContext to false, the processing stops and the action method isn’t invoked and the remaining filters aren’t executed.
On the other hand, if authorization passes, then the execution process keeps going and the other filters are executed in the order. First, the IActionFilters + action method filters are executed. Then it’s time for running the IResultFilter filters. As you might expect, the IExceptionFilter will only be used if an exception is generated during these steps.
Using filters is a good option for intercepting the several steps. It’s also important to know that the Controller base class implements the interfaces presented on the previous lists by introducing several protected virtual methods and that those methods end up being called by the ControllerActionInvoker object. In practice, this means that you can also override those methods in your controller instead of attaching new derived custom filter classes to the method calls.
And this is getting too long, so I’ll just stop now. Keep tuned for more thoughts on the MVC platform.