Abfragen auf potentiell auftretende Ausnahmen können den Code einzelner API-Methoden aufblähen. Mehrfach muss dasselbe geschrieben werden und unleserlich wird es auch. Zudem gibt es Fehler, die nicht per Code behandelt werden können. Deswegen – und damit Gleiches immer gleich behandelt wird – verwendet man für derartige Fälle eine globale Fehlerbehandlung. Dieser Beitrag zeigt wie dies funktioniert.

Abfragen auf potentiell auftretende Ausnahmen können den Code einzelner API-Methoden aufblähen. Mehrfach muss dasselbe geschrieben werden und unleserlich wird es auch. Zudem gibt es Fehler, die nicht per Code behandelt werden können. Deswegen – und damit Gleiches immer gleich behandelt wird – verwendet man für derartige Fälle eine globale Fehlerbehandlung.

Exception Filter

Mit Hilfe von Exception Filters kann der Umgang der Web API mit Ausnahmen beeinflusst werden. Diese werden ausgeführt, wenn eine Ausnahme in einem Controller ausgelöst wird. Ausnahmen vom Typ HttpResponseException sind davon nicht betroffen und werden von der Web API bereits gesondert behandelt (Rückgabe eines HTTP Status Code etc.).

Um einen Exception Filter zu implementieren, ist von der Klasse ExceptionFilterAttribute aus dem Namespace System.Web.Http.Filters abzuleiten. Durch Überschreiben der Methode OnException ist die gewünschte Logik hinzuzufügen. Wer möchte kann auch IExceptionFilter aus dem Namespace System.Web.Http implementieren, muss hier jedoch mit ein wenig mehr Aufwand rechnen.

Im nachfolgenden Beispiel wird beim Auftreten irgendeiner Ausnahme geloggt. Anschließend wird der Eigenschaft Response des Kontextes eine HttpResponseMessage mit HTTP Status Code 500 (Internal Server Error) zugewiesen. D.h. der Client erhält eine Antwort, dass die Anfrage durch ein am Server aufgetretenes Problem nicht ausgeführt werden konnte.

public class GlobalErrorHandlingFilterAttribute 
       : ExceptionFilterAttribute
{
    private readonly Log log = LogFactory.Create(typeof(GlobalErrorHandlingFilterAttribute));

    public override void OnException HttpActionExecutedContext context)
    {
        // Add logging here
        if (context.Exception != null)
        {
            log.WithMessage(context.Exception.Message)
               .WithException(context.Exception)
               .AsError();
        }
        context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
   }
}

Die Implementierung des Filters ist nicht ausreichend, er muss zusätzlich registriert werden.

Registrierung eines Exception Filters

Ein Exception Filter kann für unterschiedliche Gültigkeitsbereiche registriert werden:

  • Action
  • Controller
  • Global

Da es sich hierbei um ein Attribut handelt, ist es in den ersten beiden Fällen entweder auf Controller-Methoden (Action) oder direkt an der Controller-Klasse zu setzen.

Action

public class SampleController : ApiController
{
    [GlobalErrorHandlingFilter]
    public SampleEntity Get(long id)
    {
        // code goes here
    }
}

Controller

[GlobalErrorHandlingFilter]
public class SampleController : ApiController
{
    public SampleEntity Get(long id)
    {
        // code goes here
    }
}

Die globale Registrierung unterscheidet sich hiervon gezwungenermaßen. Im Falle von Katana (Microsofts Owin-Implementierung) sieht das so aus:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();

        // add filter for a global error handling
        config.Filters.Add(new GlobalErrorHandlingFilterAttribute());

        // activate web api
        app.UseWebApi(config);
    }
}

Fertig ist die Grundlage zur globalen Fehlerbehandlung und kann nun den eigenen Bedürfnissen entsprechend erweitert werden.

Über den Autor

Norbert Eder

Ich bin ein leidenschaftlicher Softwareentwickler und Fotograf. Mein Wissen und meine Gedanken teile ich nicht nur hier im Blog, sondern auch in Fachartikeln und Büchern.