Comment ajouter des filtres globaux d'API Web ASP.Net?

98

J'ai créé un filtre Web Api (en utilisant System.Web.Http.Filters.ActionFilterAttribute) mais je ne parviens pas à le faire fonctionner dans ASP.Net MVC 4. J'ai essayé de l'ajouter à la RegisterGlobalFilters()méthode, mais cela n'a pas fonctionné.

Donc, si l'on utilise Web Api hébergé dans ASP.Net MVC, comment enregistrer les filtres?

Shane Courtrille
la source

Réponses:

110

Le code suivant, dans mon Global.asax, fonctionne pour moi:

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

protected void Application_Start()
{
  RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Dave Bettin
la source
6
Quelqu'un peut-il expliquer ce qui se passe ici? Pourquoi existe-t-il deux ensembles de filtres globaux? Cela ne fait-il pas de «Global» un oxymore?
Luke Puplett
6
Un ensemble de filtres est pour MVC et l'autre pour l'API Web. Ce sont deux choses distinctes et normalement vous ne voudriez pas que des filtres soient appliqués pour l'un à l'autre.
Shane Courtrille
2
Mon filtre WebApi est appelé deux fois. Quelqu'un at-il ce problème?
Andrew Kalashnikov
87

notez que cette réponse est vraie jusqu'à MVC 5 / Web API 2

Réponse courte: Les filtres MVC et Web API ne sont pas compatibles entre eux et si vous souhaitez les enregistrer globalement, vous devez utiliser les classes de configuration appropriées pour chacun.

Réponse longue: ASP.NET MVC et l'API Web sont délibérément conçus pour fonctionner de la même manière, mais ce sont en fait des créatures différentes.

L'API Web vit sous l' System.Web.Httpespace de noms, tandis que MVC vit sous l' System.Web.Mvcespace de noms. Les deux vivront heureusement côte à côte, mais l'un ne contient pas l'autre et malgré les similitudes dans le modèle de programmation, les implémentations sous-jacentes sont différentes. Tout comme les contrôleurs MVC et les contrôleurs d'API Web héritent de différentes classes de contrôleur de base (MVC est simplement nommé Controlleret l'API Web est nommé ApiController), les filtres MVC et les filtres d'API Web héritent de différentes FilterAttributeclasses (les deux partagent le même nom dans ce cas, mais sont des classes distinctes qui vivent dans leurs espaces de noms respectifs).

Les filtres globaux de l'API Web sont enregistrés via l' HttpConfigurationobjet mis à votre disposition dans la Registerméthode WebApiConfig.cs si vous utilisez un modèle de projet avec WebActivator:

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

ou autrement dans le global.asax.cs:

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

Mvc filtres globaux sont enregistrés au moyen d'un GlobalFilterCollectionobjet, qui est à votre disposition par la RegisterGlobalFiltersméthode de FilterConfig.cs pour les projets qui utilisent WebActivator:

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

ou dans le fichier global.asax.cs en guise de GlobalFilters.Filterscollecte pour ceux sans WebActivator:

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

Il est à noter que dans les deux cas, vous n'avez pas besoin d'hériter du FilterAttributetype approprié . Les filtres d'API Web doivent uniquement implémenter l'interface System.Web.Http.IFilter, tandis que l'inscription de filtre MVC vérifie que votre classe hérite de l'une des rares interfaces de filtre définies dans l' System.Web.Mvcespace de noms.

joelmdev
la source
L'ajout de filtres Web Api personnalisés dans webapiconfig.cs fonctionne pour moi. Je ne comprends pas pourquoi cela n'a pas fonctionné lorsqu'il a été ajouté dans
global.asax.cs
merci @tatipaka. l'ajout au webapiconfig a fonctionné.
Gokulnath
12

À partir de MVC 4 RC, le nom de classe correct est HttpFilterCollection :

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

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

Au lieu d'utiliser des filtres globaux, je préfère faire ceci:

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

Et après cela, héritez de tous les contrôleurs api de CustomizedApiControllerBase Cette approche est plus expressive que les filtres globaux du fichier global.ascx.

Mahmoud Moravej
la source
J'ai créé un filtre héritant de System.Web.Http.Filters.ActionFilterAttribute et j'ai procédé à son utilisation directement sur les méthodes dont j'en ai besoin. Cela fonctionne, alors pourquoi n'ai-je pas besoin de l'enregistrer?
joedotnot le
@joedotnot Il s'agit de filtres "globaux" et non de filtres spécifiques. Si vous pouvez spécifier la méthode que vous souhaitez filtrer, votre approche est correcte, mais lorsque vous souhaitez filtrer quelles que soient les actions du contrôleur, vous avez besoin de filtres globaux.
Mahmoud Moravej