63

I'm new to the whole MVC thing and am looking at re-implementing some WCF services using ASP.NET Web API. As part of that, I'd like to implement an action filter that logs all actions and exceptions as well as does timing so I thought I'd start with an Action Filter, however the filter is not being invoked.

public class MyTrackingActionFilter : ActionFilterAttribute, IExceptionFilter 
{
    private Stopwatch stopwatch = new Stopwatch();

    public void OnException(ExceptionContext filterContext)
    {
           ...
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
           ...
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        this.stopwatch.Start();
        Trace.TraceInformation(" Entering {0}", filterContext.RouteData);
    }
}

and on the controller, I have

[MyTrackingActionFilter]
public class MyResourceController : ApiController
{
  ...
}

The routes are setup in Global.asax using calls like:

var routeTemplate = ...
var defaults = new { controller = controllerName, action = methodName };
var constraints = new { httpMethod = new HttpMethodConstraint(myHTTPMethods.Split(',')) };

routes.MapHttpRoute(methodName, routeTemplate, defaults, constraints);

The issue is that the actions on the MyResourceController are invoked as expected and run successfully. The client is able to query the server for the necessary info and all behaves fine, except that none of the action filter methods are ever invoked.

My understanding was that the rest happened "automagically". That's clearly not enough - Any sugestions as to what is wrong? Do I need to register these somewhere?

yu yang Jian
  • 6,680
  • 7
  • 55
  • 80
WildeButNotOscar
  • 639
  • 1
  • 5
  • 3
  • NOTE: I've tried adding the attribute to both the operation as well as the class and neither way worked. – WildeButNotOscar Apr 24 '12 at 23:43
  • BE 100% sure your API Controller related classes uses the ActionFilter from System.Web.HttpFilters and NOT the one from System.Web.Mvc – S P Apr 25 '12 at 00:05
  • At the top you should see something like: using System.Web.HttpFilters; – S P Apr 25 '12 at 00:05

2 Answers2

191

You have to be sure your code uses the ActionFilterAttribute from the System.Web.Http.Filters namespace and not the one from System.Web.Mvc.

So please check that you have

 using System.Web.Http.Filters;
Liam
  • 27,717
  • 28
  • 128
  • 190
S P
  • 4,615
  • 2
  • 18
  • 31
  • 1
    For those wondering, use System.Web.Mvc if you are building Mvc application and use System.Web.Http.Filters if you are building Web Api (controller inherited from ApiController) – Quad Coders Feb 15 '17 at 23:35
  • 2
    If this is in an assembly you need to include the [Microsoft.AspNet.WebApi.Core NuGet package](https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Core/) – Liam Mar 19 '18 at 15:29
3

As Sander mentioned I tried the below code, its action filter is getting executed.

public class WebAPIActionFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        PersonController.Messages.Add("OnActionExecuted");
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        PersonController.Messages.Add("OnActionExecuting");
    }
}

public class WebAPIExceptionFilter : System.Web.Http.Filters.ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        PersonController.Messages.Add("OnException");
        actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent("Something went wrong") };
    }
}

PersonController.Messages is a static string list. if you want to check whether OnActionExecuted is getting executed or not, you may call the same API method again, you would see the "OnActionExecuted" in the Messages list.

Liam
  • 27,717
  • 28
  • 128
  • 190
Murali
  • 63
  • 5