Archive for July 8th, 2008

08
Jul

The Forgotten Delegate…

Last week I was doing some pair programming with Jason Olson and we were looking over a project I’m working on in connection with ASP.NET MVC and custom ControllerActionInvokers (more on this to come). As he was critiquing my code, he pointed out my usage of a Func<T, bool>, asking why I wasn’t using a Predicate<T>, which achieves the exact same thing, without having to redundantly specify the boolean return type (not to mention the semantic value it adds). My response: “Umm, because I forgot about that”.

Apparently when .NET 3.5 was released I fell in such deep love with the Func delegate that I completely gave up on ever using Predicate again, which seems pretty ridiculous. Obviously Func has many more forms than Predicate, and merits lots of usage, but blindly using it for everything would begin to demean its value. Luckily I didn’t forget about my beloved Comparison delegate, so you wouldn’t ever catch me using a Func<T1, T2, int> (where T1 and T2 where the same type) as opposed to a Comparison<T>.

After feeling a little pathetic, low-and-behold I began seeing instances all over the place of people doing the exact same thing I was doing. I’ve since stumbled upon three different open-source projects that have code using Func<T, bool> delegates instead of Predicate<T>. In addition, I remembered that ADO.NET Data Services implement their query interceptors as methods whose return type is Expression<Func<T, bool>>. Apparently I’m not the only person who has fallen victim to the forgotten delegate…

I’m by no means stating that using a Func<T, bool> as opposed to a Predicate<T> is bad or anything, I just found it somewhat interesting that Funcs have permeated code that would have otherwise used another delegate.

08
Jul

ASP.NET MVC - Action Filters

When developing an ASP.NET MVC application, where all user and model interaction is routed through a controller, you will no doubt have some degree of common behavior that you’d like to prevent from being replicated across multiple action methods. This could be handled any number of ways, such as creating helper classes that your action logic makes use of, or creating base controller classes that provide shared behaviors to subtypes.

While both of those solutions have their place, neither are by any means a silver bullet. If you go the helper class route, while you’ve moved the shared behavior into a central location, you’re still going to have to repeatedly call into the helper from within the body of every action that wants to make use of it. While that isn’t horrible in itself, sometimes the common logic you wish to leverage doesn’t naturally fit with the domain/space a controller or action is responsible for.

For example, imagine that you have a UserController that is responsible for handling all requests for interacting with the user model. Simple enough. Now imagine that the customer wants to have an auditing system in place that logs every request/interaction with the UserController. If you starting placing calls to your logging system within the confines of your action methods, it would only litter and confuse the true purpose of the controller, which is to orchestrate user-interaction with user data. This is what is called a cross-cutting concern, a problem that is handled nicely by Aspect-Oriented Programming (AOP) patterns.

Essentially what we need to do in this situation is have some way to associate our logic behavior with all action methods we want to use it, but without having to explicitly place the code that uses it within the body of the action. In addition, we’d need to be able to specify whether we want the shared logic to execute before or after the action method has executed. We could use an AOP framework to achieve this, but wouldn’t it be great if ASP.NET MVC itself provided such a feature?

ASP.NET MVC has the notion of action filters that represent “hooks” you can add to a controller or action that allow you to perform arbitrary logic before and after the execution of the action method as well as the action result. In its simplest form, an action filter is a class that implements the IActionFilter interface, which contains four self-explanatory virtual methods (just begging to be overriden):

  1. OnActionExecuted
  2. OnActionExecuting
  3. OnResultExecuted
  4. OnResultExecuting

Out-of-the-box, ASP.NET MVC provides two classes that implement the IActionFilter interface: Controller, and ActionFilterAttribute. Because the Controller class is itself an action filter, you can insert pre/post logic into the pipeline on an ad-hoc basis for a specific controller by simply overriding one or more of the four aforementioned methods. Using the above example, if I wanted to log data directly before an action was executed, as well as directly after its corresponding action result was executed, I could do something similar to the following:

public class UserController : Controller 
{ 
    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
        // Run pre logging code 
    }       
 
    protected override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
        // Run post logging code 
    }       
 
    // Action methods 
}

Now our action methods are free to be concerned with only their responsibility, while the filters handle any supporting concerns. This is useful, but doesn’t serve our problem when we want our logic to be shared by many different controller actions. We could create a base controller that is used by all other controllers in our application, but what if we only want the filter logic to be performed by select actions on a controller? Further still, we might feel that placing these cross-cutting concerns directly within our controller doesn’t feel natural to our situation. This is where the ActionFilterAttribute comes in handy.

The ActionFilterAttribute is simply a class that inherits from Attribute and implements IActionFilter. It has the same four methods (pre/post hooks) as mentioned above, and any (or all) can be easily overridden. The ActionFilterAttribute is great because it encapsulates the concerning logic completely, masking its internals from either the controller or the action. In order to use it all you have to do is attach it to either a controller (which will apply that filter to all child actions) or to a specific action method. This allows a level of granularity and abstraction that using the Controller itself as a filter doesn’t. We could port the above sample to use ActionFilterAttributes like so:

[LoggingActionFilter] 
public class UserController : Controller 
{ 
    // Action methods 
}       
 
public class LoggingActionFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
        // Run pre logging code 
    }       
 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
        // Run post logging code 
    } 
}

Now our controller is free of all logic it isn’t (and arguably shouldn’t be) concerned with. Alternatively, if we didn’t want to have a filter affect all actions within a controller, instead of attaching the filter to the controller itself, we could salt an action method with it, like so:

public class UserController : Controller 
{ 
    [LoggingActionFilter] 
    public ActionResult Index() 
    { 
        // Action logic 
    }       
 
    // Additional Action methods 
}

I could now begin associating my new logging filter with any action or controller that needed its logic, without having to replicate any code, or clutter my controller.

What happens though when I want to associate numerous action filters to a controller/action? Because they’re just attributes, I can attach as many filters as I want:

[LoggingActionFilter] 
[AuthenticationActionFilter] 
[SomeOtherActionFilter] 
public ActionResult Index() 
{ 
    // Action logic 
}

In the above example, it wouldn’t make sense to perform logging logic when the authentication filter might cause the user to be redirected to another action (or controller). In this case, what we’d need is some way to specify an order of operations for our filters. Luckily, the ActionFilterAttribute has a property that allows us to explicitly set on order. By default, the filters are executed top down (well kind of), so in our case, LoggingActionFilter would run, then AuthenticationActionFilter, and finally SomeOtherActionResult. I said “kind of” because this isn’t behavior you should be relying on, and isn’t documented or expected to always work this way. If the execution order of you filters matter, you should be explicitly setting it, like so:

[LoggingActionFilter(1)] 
[AuthenticationActionFilter(0)] 
[SomeOtherActionFilter(2)] 
public ActionResult Index() 
{ 
    // Action logic 
}

Now we have full control over what order the filters run in. You may be wondering how the order of filters works if you have filters applied at both the controller and action level (and potentially even by overriding the Controller’s filter methods). For instance, what if I had code similar to the following:

[LoggingActionFilter] 
public class UserController : Controller 
{ 
    protected override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
        // Arbitrary logic 
    }       
 
    [AuthenticationActionFilter] 
    public ActionResult Index() 
    { 
        // Action logic 
    }       
 
    // Additional Action methods 
}

What order are those three filters run in? The overriden Controller methods are always first, so in our case, the OnActionExecuted method would have precedence regardless what order you specify on your filter attributes. Second, all controller-level filter attributes are run. Their order of execution is subject to the same rules mentioned above for action-level filter attributes. Finally, all action-level filter attributes are executed.

Action filters represent a reusable piece of functionality that can leveraged by many different applications needing to take advantage of common concerns without directly adding that logic within their own code base. You can expect to see lots of interesting filters surface over time by both the community as well as third-parties.