views:

168

answers:

2

I asked a question earlier today about ActionFilters in ASP.Net MVC. It turned out my problem was really that my ActionFilter is not even running. Among other things I read this article, and I can't find anything he does that I don't.

This is my code:

// The ActionFilter itself
public class TestingIfItWorksAttribute : ActionFilterAttribute
{
 public override void OnActionExecuting(ActionExecutingContext filterContext)
 {
  filterContext.Controller.TempData["filter"] = "it worked!";
  base.OnActionExecuting(filterContext);
 }
}

// The Controller Action with the filter applied
[TestingIfItWorks]
public ActionResult Test()
{
 var didit = TempData["filter"];
 return View();
}

A breakpoint in the filter method is never hit when I debug, and TempData["filter"] holds a null value when the view is rendered.

Why is this not working?

+1  A: 

Based on your comments to another answer

When testing via unit tests, the filter is not invoked. If you want to invoke the filter then you'll need mimic the ControllerActionInvoker. It's probably better, to test the filter itself in isolation, then use reflection to ensure that the filter is applied to your action with the correct attributes. I prefer this mechanism over testing the filter and action in combination.

Original

Surely you need an override on your method otherwise you aren't actually replacing the method on the base class. I would have expected the compiler to complain that you needed either a new or override on it. If you don't include the override keyword, it will behave as if you used new. Since the framework invokes it as an ActionFilterAttribute, this means that your method will never get called.

Quoting from MSDN:

If the method in the derived class is not preceded by new or override keywords, the compiler will issue a warning and the method will behave as if the new keyword were present.

tvanfosson
Hm... strange that it did not get in there. I didn't get a warning (until I recompiled) but including override did not change the situation: The code still does not run.
Tomas Lycken
Did you do a Rebuild Solution? Perhaps a library is out of date. I can't imagine this not working if you're using override.
tvanfosson
I did. No luck... =(
Tomas Lycken
Thanks! I figured it out about the same time by starting a new, clean project, adding just the necessary to test this (a controller, a filter, a view and a test) and I found out the same thing. I'll look around on the net for some info on unit testing ActionFilters separately and get back with a new question if I fail (again). Big thanks! =)
Tomas Lycken
A: 

In addition to what tvanofosson said, your action method isn't actually rendering anything to the view. Does your view have a <%=TempData["Filter"].ToString()%> statement or something similar?

Chris
No, I don't actually have a view. I have a breakpoint in the ActionResult method in the controller, and a breakpoint in the OnActionExecuting method in the filter, and a UnitTest that calls the action. I hit "Debug test" and stop in the controller action, but not in the filter action. In addition, the unit test tries to assert that TempData["filter"] == "it worked!", and fails.
Tomas Lycken
Aha -- the attribute isn't invoked from the unit test, it's only invoked by the MVC framework when the method is called by the action executor.
tvanfosson