In-lining mapping and injection aspects – yuck!

After implementing several aspects of controller actions as compos-able filters, it became apparent that controlling the order would be import. One of the latest additions is a filter to build up a view model property with data aspects. An example would be a select list for states on a person edit view. Normally, the states would be fetched and set on the model in the controller action:

Extracting the injection aspect

This leads to repetitive code every time a view model requires this data. Furthermore, we are forced to create the appropriate view model inside the controller action instead of relying on the mapping filter. To separate concerns we created a filter to find these data aspects and inject the values. Now, we simply add a property to the view model and the filter will take care of the rest!

IFilterPriority - Back to the aspect!

In the example, PersonViewModel can be built up with a list of states, if the mapping filter is executed first. To guarantee this, I have added an interface IFilterPriority with a routine GetOrder() to the IJoinedFilter framework. It returns an integer representing the priority of the filter in the execution chain. I chose an integer to mirror FilterAttribute.Order in the MVC framework, which sadly was not made into a compo-sable extensibility point.

public interface IFilterPriority
{
int GetOrder();
}

JoinedFilterLocator has been modified to add filters based on this order to the FilterInfo result. The actual execution is dependent on the MVC pipeline and follows the following rules when using JoinedFilterLocator:

Now, we can set the priority of our mapping filter to 1, ensuring it’s OnActionExecuted is executed first. All other filters in the JoinedFilter project are given an order of Int32.Max by default. This might not be the best way to sort, so watch out for updates in the future. This seems to work well with action filters and exception filters.

Prioritizing exception aspects

Exception filters are another good example where priority becomes important. I have created a sample set of exceptions NestedException inheriting from ExceptionBase. I added two methods to the PriorityController sample:

What if we want one handler to catch specific exceptions of type NestedException and another to handle the more general exception ExceptionBase? Without priority, we are at the mercy of JoinedFilterLocator and whatever mechanism it relies on to acquire JoinedFilters. The sample below implements two handlers to send users to an error view with a message reporting what exception handler dealt with the error:

Run the sample yourself and try changing the priority to see how the ExceptionBaseHandler and NestedExceptionHandler work. Notice how this allows control over exception handlers from most specific to most general, just like with try/catch statements.

As usual, all code is available at my Google code repository for IJoinedFilter, this set of changes was wrapped up with commit 56. Please leave me some feedback about any enhancements, specifically I am looking for better ideas to deal with priority of filters, the integer thing kind of bothers me :).

Update: I am thinking that another nice way to do priority would be to use an explicit configuration mechanism, a lot like FubuMvc has so the filters being used are explicit and the order listed is the order applied. Thoughts?