¿Cómo agregar filtros globales de API web ASP.Net?

98

Creé un filtro Web Api (usando System.Web.Http.Filters.ActionFilterAttribute) pero no puedo hacer que funcione dentro de ASP.Net MVC 4. Intenté agregarlo al RegisterGlobalFilters()método pero no funcionó.

Entonces, si uno está utilizando Web Api alojado en ASP.Net MVC, ¿cómo se registran los filtros?

Shane Courtrille
fuente

Respuestas:

110

El siguiente código, en mi Global.asax, funciona para mí:

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

protected void Application_Start()
{
  RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Dave Bettin
fuente
6
¿Alguien puede explicar qué está pasando aquí? ¿Por qué hay dos conjuntos de filtros globales? ¿No hace eso que 'Global' sea un oxímoron?
Luke Puplett
6
Un conjunto de filtros es para MVC y el otro es para API web. Son dos cosas separadas y normalmente no querrá que se apliquen filtros para uno al otro.
Shane Courtrille
2
Mi filtro WebApi se llama dos veces. ¿Alguien tiene este problema?
Andrew Kalashnikov
87

tenga en cuenta que esta respuesta es cierta hasta MVC 5 / Web API 2

Respuesta corta: los filtros MVC y Web API no son compatibles entre sí, y si desea registrarlos globalmente, debe usar las clases de configuración adecuadas para cada uno.

Respuesta larga: ASP.NET MVC y Web API están específicamente diseñadas para funcionar de manera similar, pero de hecho son criaturas diferentes.

La API web vive bajo el System.Web.Httpespacio de nombres, mientras que MVC vive bajo el System.Web.Mvcespacio de nombres. Los dos vivirán felizmente uno al lado del otro, pero uno no contiene al otro y, a pesar de las similitudes en el modelo de programación, las implementaciones subyacentes son diferentes. Así como los controladores MVC y los controladores Web API heredan diferentes clases de controlador base (MVC simplemente se nombra Controllery Web API ApiController), los filtros MVC y los filtros Web API heredan de diferentes FilterAttributeclases (ambos comparten el mismo nombre en este caso, pero son clases separadas que viven en sus respectivos espacios de nombres).

Los filtros globales de la API web se registran a través del HttpConfigurationobjeto disponible para usted en el Registermétodo WebApiConfig.cs si está utilizando una plantilla de proyecto con WebActivator:

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

o de lo contrario en global.asax.cs:

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

Los filtros globales de Mvc se registran mediante un GlobalFilterCollectionobjeto, que está disponible a través del RegisterGlobalFiltersmétodo de FilterConfig.cs para proyectos que utilizan WebActivator:

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

o en el archivo global.asax.cs a modo de GlobalFilters.Filterscolección para aquellos sin WebActivator:

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

Vale la pena señalar que en ambos casos no es necesario heredar del FilterAttributetipo apropiado . Los filtros de API web solo necesitan implementar la interfaz System.Web.Http.IFilter, mientras que el registro del filtro MVC verifica para garantizar que su clase herede una de las pocas interfaces de filtro definidas en el System.Web.Mvcespacio de nombres.

joelmdev
fuente
Agregar filtros personalizados de Web Api en webapiconfig.cs me funciona. No entiendo por qué no funcionó cuando se agregó en global.asax.cs
Tatipaka
gracias @tatipaka. la adición al webapiconfig funcionó.
Gokulnath
12

A partir de MVC 4 RC, el nombre de clase correcto es HttpFilterCollection :

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

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

En lugar de usar filtros globales, prefiero hacer esto:

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

Y después de eso, hereda todos los controladores api de CustomizedApiControllerBase Este enfoque es más expresivo en comparación con los filtros globales en el archivo global.ascx.

Mahmoud Moravej
fuente
Creé un filtro heredado de System.Web.Http.Filters.ActionFilterAttribute y procedí a usarlo directamente en los métodos que lo necesito. Simplemente funciona, ¿por qué no necesito registrarlo?
joedotnot
@joedotnot Se trata de filtros "globales", no específicos. Si puede especificar qué método desea filtrar, su enfoque es correcto, pero cuando desea filtrar independientemente de las acciones del controlador, necesita filtros globales.
Mahmoud Moravej