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.