Sep 11

The MVC platform – a more detailed view on how your filters are run

Posted in ASP.NET MVC      Comments Off on The MVC platform – a more detailed view on how your filters are run

In one of the previous posts, we’ve seen how controller action methods are executed. At the time, we didn’t really dig deep into the code so today we’ll see how all those actions filters are setup in order to set up a calling stack that garantees that your filters are run in the correct order. In the previous post, we’ve seen how the authorization and exception filters are used. Today, we’ll concentrate on the action and result filters. Before going on, I’d just like to remind you that there’s already an abstract ActionFilterAttribute that implements both interfaces presented here. If you want to build your own filters, just expand this class and override the necessary methods.

Internally, after running the authorization filters, the ControllerActionInvoker breaks filter invocation in two steps. First, the so called action filters are executed. This means that all the IActionFilters + action method are invoked in one step (recall that IActionFilter will also introduce two methods that are run before and after the action method invocation). After, it’s time for the result filters do their work in a second step. It’s on this second step that your views will get executed and generate the response that is sent back to the client.

Lets start with the action filters… Action filters implement the IActionFilter interface, which looks like this:

public interface IActionFilter {
        void OnActionExecuting(ActionExecutingContext filterContext);
        void OnActionExecuted(ActionExecutedContext filterContext);

The OnActionExecuting method will be called before the action method is executed; on the other hand,OnActionExecuted method will be called after your action method has done its work. As you surelly know,action methods (which are the methods you put in your custom controllers) will always return a ActionResult object which will be responsible for generating the response returned to the client (most times, this means that this class wiell end up controlling the generations of the HTML sent back to the client).

The ActionExecutingContext is an auxiliary class which is used for passing the current context between all the filters interested in handle the OnActionExecuting method. One of the properties exposed by this class is called Result and it will let you influence the ActionResult associated with the current call. If you set this value from within the OnActionExecuting method of any of your filters, then you’re stopping any further processing on your action filters and the current action method won’t be called either. Do notice that the IResultFilter methods (which we’ll be talking about on the next paragraphs) will still be called.

As you might expect, if you don’t set up the Result property from within any of your action filter’s OnActionExecuting methods, then the other OnActionExecuting methods of the other filters will be called and your action method will get executed and will be returning an instance of ActionResult type.

When you implement the OnActionExecuted method, you’ll end up receiving an instance of type ResultExecutedContext. Besides letting you get access to the currentControllerContext, you’ll also get properties for

  • getting the ActionResult (property Result) responsible for generating the response returned to the client;
  • seeing if the processing was cancelled (which happens when, for instance, you set the Result property of the ActionExecuting context from within the OnActionExecuting method). You can get this info from the Canceled property;
  • getting a reference to an exception that might have been generated during the processing (as you might expect, this is available through the Exception property);
  • indicating that you’ve handled an exception (property ExceptionHandled).

In previous releases, you would probably use this method for handling exceptions. You can still do this, but don’t forget that now you have the IExceptionFilter filters which are excellent for that kind of processing. After all these steps, it’s time for the IResultFilter filters to do their work. Notice that this is the second part of the filters execution work I’ve mentioned at the beginning of this post. The IResultFilter interface looks like this:

public interface IResultFilter {
        void OnResultExecuting(ResultExecutingContext filterContext);
        void OnResultExecuted(ResultExecutedContext filterContext);

As you can see, it has a similar API to the IActionFilter Interface . The ResultExecutingContext is a little different from the ActionExecutingContext we’ve talked about. If you build one of these filters, then you can cancel further processing by setting the Cancel property to true from within the OnResultExecuting method. Notice that when this happens, your view won’t be called and you end up not generating the HTML that is generally sent back to the client (I’m assuming a simple case, where you have a view that generates HTML. As we’ll see, you can also have a view that generates JSON…).

A result filter can also implement the OnResultExecuted method. In that case, you’ll end up receiving an instance of the ResultExecutedContext type. This class is very similar to the ActionExecuted type and one of the things you can do from within the method is handle exceptions (again, don’t forget that you can do that with the IExceptionFilter filters). It’s important to understand that this method will be called after your view has generated the response that is going to be sent back to the client. In the future, we’ll talk more about the different types of views and their relationship with the ActionResult class.

At this time, feel free to look at the source code…It’s really “beautiful” code which is hard to read since it makes heavy use of LINQ and reflection. Here’s a snippet from the method that is responsible for performing the first step associated with filter execution (ie, the method that controls action filters execution):

protected virtual ActionExecutedContext InvokeActionMethodWithFilters(
              MethodInfo methodInfo,
              IDictionary<string, object> parameters,
              IList<IActionFilter> filters) {
     ActionExecutingContext preContext =  …;
     Func<ActionExecutedContext> continuation =
               () => new ActionExecutedContext(ControllerContext,
                                                                        false /* canceled */,
                                                                         null /
* exception */)
                    Result = InvokeActionMethod(methodInfo, parameters)
  Func<ActionExecutedContext> thunk =
                               (next, filter) =>
                                      () => InvokeActionMethodFilter(
                                                               filter, preContext, next));
  return thunk();

I’ve removed unecessary initializations from the previous method so that we can concentrate on the essential…

Look at how they’re using aggregation to invoke the filters and execute the current action method. As you can see,the seed of the Aggregate (continuarion variable) method is a Func delegate which returns an ActionExecutedContext that has its Result property set by calling the current action method.  Not really its normal usage, but it works!

The goodies don’t end there: look at how they’ve defined the Func delegate passed as the second parameter to the Aggregate method…That means that your aggregate method has the following signature:

  Func<Func<ActionExecutedContest>,IActionFilter, Func<ActionExecutedContest>>

Man, not sure about you, but I did loose sometime trying to understand this piece of code. It’s not that common to have an aggregate that returns a Func delegate which you call in order to start other methods invocations…

Even though it’s not that readable, you can’t simply deny its elegance and compactness…and of course, you’ll be sick after spending enough time looking at it (at least, I’m feeling like that now that I’ve understood what’s going on 🙂 )

Something very similar happens to the 2nd part of filter processing, but I’ll leave that investigation to you 🙂

On the next post, we’ll start looking at ActionResult types and see how they’re used for interacting with your views. Keep tuned!