Wie füge ich globale ASP.Net-Web-API-Filter hinzu?

98

Ich habe einen Web-API-Filter (mit System.Web.Http.Filters.ActionFilterAttribute) erstellt, kann ihn jedoch nicht in ASP.Net MVC 4 zum Laufen bringen. Ich habe versucht, ihn der RegisterGlobalFilters()Methode hinzuzufügen, aber das hat nicht funktioniert.

Wenn man also eine in ASP.Net MVC gehostete Web-API verwendet, wie registriert man Filter?

Shane Courtrille
quelle

Antworten:

109

Der folgende Code in meiner Global.asax funktioniert für mich:

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

protected void Application_Start()
{
  RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Dave Bettin
quelle
6
Kann jemand erklären, was hier los ist? Warum gibt es zwei Sätze globaler Filter? Macht das nicht 'Global' zu einem Oxymoron?
Luke Puplett
6
Ein Satz von Filtern ist für MVC und der andere für die Web-API. Dies sind zwei getrennte Dinge, und normalerweise möchten Sie nicht, dass Filter für einen auf den anderen angewendet werden.
Shane Courtrille
2
Mein WebApi-Filter wird zweimal aufgerufen. Hat jemand dieses Problem?
Andrew Kalashnikov
87

Beachten Sie, dass diese Antwort bis zu MVC 5 / Web API 2 gilt

Kurze Antwort: MVC- und Web-API-Filter sind nicht miteinander kompatibel. Wenn Sie sie global registrieren möchten, müssen Sie jeweils die entsprechenden Konfigurationsklassen verwenden.

Lange Antwort: ASP.NET MVC und Web API sind absichtlich so konzipiert, dass sie auf ähnliche Weise funktionieren, aber es handelt sich tatsächlich um unterschiedliche Kreaturen.

Die Web-API befindet sich unter dem System.Web.HttpNamespace, während MVC unter dem System.Web.MvcNamespace lebt . Die beiden werden glücklich nebeneinander leben, aber eines enthält das andere nicht und trotz der Ähnlichkeiten im Programmiermodell sind die zugrunde liegenden Implementierungen unterschiedlich. So wie MVC-Controller und Web-API-Controller unterschiedliche Basis-Controller-Klassen erben (MVCs werden einfach benannt Controllerund Web-APIs werden benannt ApiController), erben MVC-Filter und Web-API-Filter von verschiedenen FilterAttributeKlassen (beide haben in diesem Fall denselben Namen, sind jedoch separate Klassen, die leben in ihren jeweiligen Namespaces).

Globale Web-API-Filter werden über das HttpConfigurationObjekt registriert, das Ihnen in der RegisterMethode WebApiConfig.cs zur Verfügung steht, wenn Sie eine Projektvorlage mit WebActivator verwenden:

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

oder anders in der global.asax.cs:

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

Globale Mvc-Filter werden über ein GlobalFilterCollectionObjekt registriert , das Ihnen über die RegisterGlobalFiltersMethode FilterConfig.cs für Projekte zur Verfügung steht, die WebActivator verwenden:

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

oder in der Datei global.asax.cs als GlobalFilters.FiltersSammlung für Personen ohne WebActivator:

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

Es ist erwähnenswert, dass Sie in beiden Fällen nicht vom entsprechenden FilterAttributeTyp erben müssen . Web-API-Filter müssen nur die System.Web.Http.IFilter-Schnittstelle implementieren, während die MVC-Filterregistrierung überprüft, ob Ihre Klasse eine von wenigen im System.Web.MvcNamespace definierten Filterschnittstellen erbt .

joelmdev
quelle
Das Hinzufügen von benutzerdefinierten Web-API-Filtern in webapiconfig.cs funktioniert für mich. Ich verstehe nicht, warum es nicht funktioniert hat, als es in global.asax.cs hinzugefügt wurde
Tatipaka
danke @tatipaka. Das Hinzufügen zur Webapiconfig hat funktioniert.
Gokulnath
12

Ab MVC 4 RC lautet der korrekte Klassenname HttpFilterCollection :

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

protected void Application_Start()
{
    RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Nuzzolilo
quelle
8

Anstatt globale Filter zu verwenden, bevorzuge ich Folgendes:

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

Und danach erben Sie alle API-Controller von CustomizedApiControllerBase Dieser Ansatz ist im Vergleich zu globalen Filtern in der Datei global.ascx aussagekräftiger.

Mahmoud Moravej
quelle
Ich habe einen Filter erstellt, der von System.Web.Http.Filters.ActionFilterAttribute erbt, und ihn direkt für die von mir benötigten Methoden verwendet. Es funktioniert einfach, warum muss ich es nicht registrieren?
Joedotnot
@joedotnot Es geht um "globale" Filter, nicht um die spezifischen. Wenn Sie angeben können, welche Methode Sie filtern möchten, ist Ihr Ansatz in Ordnung. Wenn Sie jedoch unabhängig von Controller-Aktionen filtern möchten, benötigen Sie globale Filter.
Mahmoud Moravej