I've broken this up into three parts:
I’ve decided to add more features to the before filter I’ve build in the previous post. I need a way to specify a few methods I’d like to execute before the controller actions. I can do that now by specifying a number of BeforeFilter attributes but that looks a little silly. What I want is the ability to do something like this:
[BeforeFilter("InitializeCategories","InitializeProvinces")]
This should be fairly easy to accomplish. We should probably start with a test. I’ve added a logaction method to the test controller so we can assert it was called. Here is the test:
[Test] public void should_call_all_specified_controller_methods_given_they_exist() { controller.Setup(x => x.initialize()); controller.Setup(x => x.logaction()); var attribute = new BeforeFilterAttribute("initialize", "logaction"); attribute.OnActionExecuting(context); controller.VerifyAll(); }
To make this pass we change our implementation slightly. The method names now become a collection we need to iterate over and invoke the method on the controller if found; if not, we throw and exception as before. I've changed the exception type to an InvalidOperationException.
public BeforeFilterAttribute(string methodName) : this(new[] { methodName }) { } public BeforeFilterAttribute(params string[] methods) { this.methods = new List<string>(methods); } public override void OnActionExecuting(ActionExecutingContext filterContext) { var controller = filterContext.Controller; foreach (var method in methods) { ... } base.OnActionExecuting(filterContext); }
This makes the test pass and now we have a BeforeFilter that’s a little more useful and friendly.
I would like to add one more feature to my BeforeFilter and that is an exception list. In other words, I would like a way to specify controller actions for which to NOT execute the methods. That way I have the ability to apply the BeforeFilter to the controller itself instead if the individual action and still retained fine grained control over the before methods that execute for a given action. I will leave that for a separate post.