103

I've created a Web Api filter (using System.Web.Http.Filters.ActionFilterAttribute) but I am unable to get it to work inside of ASP.Net MVC 4. I tried adding it to the RegisterGlobalFilters() method but that didn't work.

So if one is using Web Api hosted in ASP.Net MVC how does one register filters?

Shane Courtrille
  • 13,960
  • 22
  • 76
  • 113

4 Answers4

115

The following code, in my Global.asax, works for me:

public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
{
  filters.Add(new MyWebApiFilter());
}

protected void Application_Start()
{
  RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Shane Courtrille
  • 13,960
  • 22
  • 76
  • 113
Dave Bettin
  • 2,322
  • 1
  • 18
  • 9
100

note that this answer holds true up to MVC 5/Web API 2

Short answer: MVC and Web API filters are not cross compatible, and if you want to register them globally, you must use the appropriate configuration classes for each.

Long answer: ASP.NET MVC and Web API are purposely designed to work in a similar way, but they are in fact different creatures.

Web API lives under the System.Web.Http namespace, whereas MVC lives under the System.Web.Mvc namespace. The two will happily live side by side, but one does not contain the other and despite the similarities in the programming model, the underlying implementations are different. Just as MVC controllers and Web API controllers inherit different base controller classes (MVC's is simply named Controller and Web API's is named ApiController) MVC filters and Web API filters inherit from different FilterAttribute classes (both share the same name in this case, but are separate classes which live in their respective namespaces).

Web API global filters are registered through the HttpConfiguration object available to you in the Register method WebApiConfig.cs if you're using a project template with WebActivator:

public static void Register(HttpConfiguration config)
{
    //stuff before
    config.Filters.Add(new MyWebApiFilter());
    //stuff after
}

or otherwise in the global.asax.cs:

GlobalConfiguration.Configuration.Filters.Add(new MyWebApiFilter());

Mvc global filters are registered by way of a GlobalFilterCollection object, which is available to you through the RegisterGlobalFilters method of FilterConfig.cs for projects that are using WebActivator:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //stuff before
        filters.Add(new MyMvcFilter());
        //stuff after
    }
}

or in the global.asax.cs file by way of GlobalFilters.Filters collection for those without WebActivator:

GlobalFilters.Filters.Add(new MyMvcFilter());

It's worth noting that in both cases you do not need to inherit from the appropriate FilterAttribute type. Web API Filters need only implement the System.Web.Http.IFilter interface, while MVC filter registration checks to ensure that your class inherits one of a handful of filter interfaces defined in the System.Web.Mvc namespace.

joelmdev
  • 11,083
  • 10
  • 65
  • 89
12

As of MVC 4 RC, the correct class name is HttpFilterCollection:

public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
{
    filters.Add(new MyWebApiFilter());
}

protected void Application_Start()
{
    RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
marknuzz
  • 2,847
  • 1
  • 26
  • 29
8

Instead of using global filters I prefer to do this :

[MyWebApiFilter]
public class CustomizedApiControllerBase : ApiController
{
   ...
}

And after that inherit all of api controllers from CustomizedApiControllerBase This approach is more expressive in comparison with global filters in global.ascx file.

Mahmoud Moravej
  • 8,705
  • 6
  • 46
  • 65
  • I created a Filter inheriting from System.Web.Http.Filters.ActionFilterAttribute and proceeded to use it directly on the methods that I require it. It just works, so why don't i need to register it ? – joedotnot Jan 23 '19 at 04:24
  • @joedotnot It is about "global" filters not the specific ones. If you can specify which method you want to filter, your approach is OK but when you want to filter regardless of controller actions, you need global filters. – Mahmoud Moravej Jan 23 '19 at 07:44