Como adicionar filtros ASP.Net Web Api globais?

98

Eu criei um filtro Web Api (usando System.Web.Http.Filters.ActionFilterAttribute), mas não consigo fazê-lo funcionar dentro do ASP.Net MVC 4. Eu tentei adicioná-lo ao RegisterGlobalFilters()método, mas não funcionou.

Então, se alguém estiver usando Web Api hospedado no ASP.Net MVC, como registrar os filtros?

Shane Courtrille
fonte

Respostas:

110

O código a seguir, em meu Global.asax, funciona para mim:

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

protected void Application_Start()
{
  RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Dave Bettin
fonte
6
Alguém pode explicar o que está acontecendo aqui? Por que existem dois conjuntos de filtros globais? Isso não torna 'Global' um oxímoro?
Luke Puplett
6
Um conjunto de filtros é para MVC e o outro é para Web API. São duas coisas distintas e normalmente você não gostaria que os filtros de uma fossem aplicados à outra.
Shane Courtrille
2
Meu filtro WebApi é chamado duas vezes. Alguém tem esse problema?
Andrew Kalashnikov
87

observe que esta resposta é verdadeira até MVC 5 / Web API 2

Resposta curta: Os filtros MVC e Web API não são compatíveis entre si e, se você quiser registrá-los globalmente, deve usar as classes de configuração apropriadas para cada um.

Resposta longa: ASP.NET MVC e Web API são propositalmente projetadas para funcionar de maneira semelhante, mas na verdade são criaturas diferentes.

A API da Web reside no System.Web.Httpnamespace, enquanto o MVC vive no System.Web.Mvcnamespace. Os dois viverão felizmente lado a lado, mas um não contém o outro e, apesar das semelhanças no modelo de programação, as implementações subjacentes são diferentes. Assim como os controladores MVC e controladores de API da Web herdam diferentes classes de controlador de base (MVC é simplesmente nomeado Controllere API da Web é nomeado ApiController), filtros MVC e filtros de API da Web herdam deFilterAttribute classes (ambos compartilham o mesmo nome neste caso, mas são classes separadas que vivem em seus respectivos namespaces).

Os filtros globais da API da Web são registrados por meio do HttpConfigurationobjeto disponível para você no Registermétodo WebApiConfig.cs se você estiver usando um modelo de projeto com WebActivator:

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

ou de outra forma no global.asax.cs:

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

Filtros globais Mvc são registrados por meio de um GlobalFilterCollectionobjeto, que está disponível para você por meio do RegisterGlobalFiltersmétodo de FilterConfig.cs para projetos que usam WebActivator:

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

ou no arquivo global.asax.cs por meio de GlobalFilters.Filterscoleção para aqueles sem WebActivator:

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

É importante notar que, em ambos os casos, você não precisa herdar do FilterAttributetipo apropriado . Filtros de API da Web precisam apenas implementar a interface System.Web.Http.IFilter, enquanto o registro do filtro MVC verifica para garantir que sua classe herde uma das várias interfaces de filtro definidas no System.Web.Mvcnamespace.

joelmdev
fonte
Adicionar filtros de API da Web personalizados em webapiconfig.cs funciona para mim. Não entendo por que não funcionou quando adicionado em global.asax.cs
Tatipaka
obrigado @tatipaka. adicionar ao webapiconfig funcionou.
Gokulnath
12

A partir do MVC 4 RC, o nome de classe correto é HttpFilterCollection :

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

protected void Application_Start()
{
    RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
nuzzolilo
fonte
8

Em vez de usar filtros globais, prefiro fazer o seguinte:

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

E depois disso, herde todos os controladores da API de. CustomizedApiControllerBase Esta abordagem é mais expressiva em comparação com os filtros globais no arquivo global.ascx.

Mahmoud Moravej
fonte
Criei um filtro herdado de System.Web.Http.Filters.ActionFilterAttribute e comecei a usá-lo diretamente nos métodos que eu preciso. Simplesmente funciona, então por que não preciso registrá-lo?
joedotnot
@joedotnot Trata-se de filtros "globais", não de filtros específicos. Se você pode especificar qual método deseja filtrar, sua abordagem está OK, mas quando você deseja filtrar independentemente das ações do controlador, você precisa de filtros globais.
Mahmoud Moravej