Как добавить глобальные фильтры ASP.Net Web Api?

98

Я создал фильтр Web Api (использующий System.Web.Http.Filters.ActionFilterAttribute), но я не могу заставить его работать внутри ASP.Net MVC 4. Я попытался добавить его в RegisterGlobalFilters()метод, но это не сработало.

Итак, если вы используете Web Api, размещенный в ASP.Net MVC, как зарегистрировать фильтры?

Шейн Кортриль
источник

Ответы:

110

У меня работает следующий код в моем Global.asax:

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

protected void Application_Start()
{
  RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Дэйв Беттин
источник
6
Может кто-нибудь объяснить, что здесь происходит? Почему существует два набора глобальных фильтров? Разве это не превращает Global в оксюморон?
Люк Пуплетт,
6
Один набор фильтров предназначен для MVC, а другой - для веб-API. Это две разные вещи, и обычно вы не хотите, чтобы фильтры для одного применялись к другому.
Шейн Кортрилл
2
Мой фильтр WebApi вызывается дважды. Есть у кого-нибудь такая проблема?
Андрей Калашников
87

обратите внимание, что этот ответ верен до MVC 5 / Web API 2

Краткий ответ: фильтры MVC и веб-API несовместимы, и если вы хотите зарегистрировать их глобально, вы должны использовать соответствующие классы конфигурации для каждого из них.

Длинный ответ: ASP.NET MVC и веб-API специально разработаны для работы одинаковым образом, но на самом деле это разные существа.

Веб-API находится в System.Web.Httpпространстве имен, а MVC - в System.Web.Mvcпространстве имен. Эти два будут счастливо жить бок о бок, но один не содержит другого, и, несмотря на сходство модели программирования, лежащие в основе реализации разные. Так же, как контроллеры MVC и контроллеры веб-API наследуют разные базовые классы контроллеров (MVC просто именуются, Controllerа веб-API именуются ApiController), фильтры MVC и фильтры веб-API наследуются от разных FilterAttributeклассов (оба имеют одно и то же имя в этом случае, но являются отдельными классами, которые живут в их соответствующих пространствах имен).

Глобальные фильтры веб-API регистрируются через HttpConfigurationобъект, доступный вам в Registerметоде WebApiConfig.cs, если вы используете шаблон проекта с WebActivator:

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

или иначе в global.asax.cs:

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

Глобальные фильтры MVC регистрируются с помощью GlobalFilterCollectionобъекта, который доступен вам через RegisterGlobalFiltersметод FilterConfig.cs для проектов, использующих WebActivator:

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

или в файле global.asax.cs путем GlobalFilters.Filtersсбора для тех, у кого нет WebActivator:

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

Стоит отметить, что в обоих случаях наследование от соответствующего FilterAttributeтипа не требуется . Фильтры веб-API должны реализовывать только интерфейс System.Web.Http.IFilter, в то время как регистрация фильтра MVC проверяет, наследует ли ваш класс один из нескольких интерфейсов фильтра, определенных в System.Web.Mvcпространстве имен.

Joelmdev
источник
У меня работает добавление пользовательских фильтров Web Api в webapiconfig.cs. Я не понимаю, почему это не сработало при добавлении в global.asax.cs
Татипака 06
спасибо @tatipaka. добавление в webapiconfig сработало.
Gokulnath
12

Начиная с MVC 4 RC, правильное имя класса - HttpFilterCollection :

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

protected void Application_Start()
{
    RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
нуццолило
источник
8

Я предпочитаю использовать не глобальные фильтры:

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

И после этого унаследовать все контроллеры api от CustomizedApiControllerBase этого подхода более выразительно по сравнению с глобальными фильтрами в файле global.ascx.

Махмуд Моравей
источник
Я создал фильтр, унаследованный от System.Web.Http.Filters.ActionFilterAttribute, и начал использовать его непосредственно в методах, которые мне нужны. Он просто работает, так почему мне не нужно его регистрировать?
joedotnot
@joedotnot Речь идет о «глобальных» фильтрах, а не о конкретных. Если вы можете указать, какой метод вы хотите фильтровать, ваш подход в порядке, но если вы хотите фильтровать независимо от действий контроллера, вам нужны глобальные фильтры.
Махмуд Мораведж