Freigeben über


Ausnahmebehandlung in ASP.NET Web-API

In diesem Artikel wird die Fehler- und Ausnahmebehandlung in ASP.NET Web-API beschrieben.

HttpResponseException

Was geschieht, wenn ein Web-API-Controller eine nicht abgefangene Ausnahme auslöst? Standardmäßig werden die meisten Ausnahmen in eine HTTP-Antwort mit Statuscode 500, interner Serverfehler, übersetzt.

Der HttpResponseException-Typ ist ein Sonderfall. Diese Ausnahme gibt einen HTTP-Statuscode zurück, den Sie im Ausnahmekonstruktor angeben. Die folgende Methode gibt z. B. 404, Not Found, zurück, wenn der ID-Parameter ungültig ist.

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item;
}

Um mehr Kontrolle über die Antwort zu erhalten, können Sie auch die gesamte Antwortnachricht erstellen und in die HttpResponseException einschließen:

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent(string.Format("No product with ID = {0}", id)),
            ReasonPhrase = "Product ID Not Found"
        };
        throw new HttpResponseException(resp);
    }
    return item;
}

Ausnahmefilter

Sie können anpassen, wie Web-API Ausnahmen verarbeitet, indem Sie einen Ausnahmefilter schreiben. Ein Ausnahmefilter wird ausgeführt, wenn eine Controllermethode eine unbehandelte Ausnahme auslöst, die keineHttpResponseException-Ausnahme ist. Der HttpResponseException-Typ ist ein Sonderfall, da er speziell für die Rückgabe einer HTTP-Antwort entwickelt wurde.

Ausnahmefilter implementieren die Schnittstelle "System.Web.Http.Filters.IExceptionFilter" . Die einfachste Methode zum Schreiben eines Ausnahmefilters besteht darin, von der System.Web.Http.Filters.ExceptionFilterAttribute-Klasse abzuleiten und die OnException-Methode außer Kraft zu setzen.

Hinweis

Ausnahmefilter in ASP.NET Web-API ähneln denen in ASP.NET MVC. Sie werden jedoch separat in einem separaten Namespace und in einer separaten Funktion deklariert. Insbesondere behandelt die in MVC verwendete HandleErrorAttribute-Klasse keine Ausnahmen, die von Web-API-Controllern ausgelöst werden.

Hier ist ein Filter, der NotImplementedException-Ausnahmen in HTTP-Statuscode 501 konvertiert, nicht implementiert:

namespace ProductStore.Filters
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Filters;

    public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute 
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Exception is NotImplementedException)
            {
                context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
        }
    }
}

Die Response-Eigenschaft des HttpActionExecutedContext-Objekts enthält die HTTP-Antwortnachricht, die an den Client gesendet wird.

Registrieren von Ausnahmefiltern

Es gibt verschiedene Möglichkeiten zum Registrieren eines Web-API-Ausnahmefilters:

  • Nach Aktion
  • Vom Controller gesteuert
  • Weltweit

Um den Filter auf eine bestimmte Aktion anzuwenden, fügen Sie den Filter als Attribut zur Aktion hinzu:

public class ProductsController : ApiController
{
    [NotImplExceptionFilter]
    public Contact GetContact(int id)
    {
        throw new NotImplementedException("This method is not implemented");
    }
}

Um den Filter auf alle Aktionen auf einem Controller anzuwenden, fügen Sie den Filter als Attribut zur Controllerklasse hinzu:

[NotImplExceptionFilter]
public class ProductsController : ApiController
{
    // ...
}

Um den Filter global auf alle Web-API-Controller anzuwenden, fügen Sie der GlobalConfiguration.Configuration.Filters-Auflistung eine Instanz des Filters hinzu. Ausnahmefilter in dieser Auflistung gelten für jede Web-API-Controlleraktion.

GlobalConfiguration.Configuration.Filters.Add(
    new ProductStore.NotImplExceptionFilterAttribute());

Wenn Sie die Projektvorlage "ASP.NET MVC 4-Webanwendung" verwenden, um Ihr Projekt zu erstellen, fügen Sie den Web-API-Konfigurationscode in die WebApiConfig Klasse ein, die sich im Ordner App_Start befindet:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Filters.Add(new ProductStore.NotImplExceptionFilterAttribute());

        // Other configuration code...
    }
}

HttpError

Das HttpError-Objekt bietet eine konsistente Möglichkeit, Fehlerinformationen im Antworttext zurückzugeben. Das folgende Beispiel zeigt, wie http-Statuscode 404 (Nicht gefunden) mit einem HttpError im Antworttext zurückgegeben wird.

public HttpResponseMessage GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
    }
    else
    {
        return Request.CreateResponse(HttpStatusCode.OK, item);
    }
}

CreateErrorResponse ist eine Erweiterungsmethode, die in der System.Net.Http.HttpRequestMessageExtensions-Klasse definiert ist. Intern erstellt CreateErrorResponse eine HttpError-Instanz und erstellt dann eine HttpResponseMessage , die den HttpError enthält.

Wenn die Methode in diesem Beispiel erfolgreich ist, wird das Produkt in der HTTP-Antwort zurückgegeben. Wenn das angeforderte Produkt jedoch nicht gefunden wird, enthält die HTTP-Antwort einen HttpError im Anforderungstext. Die Antwort könnte wie folgt aussehen:

HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51

{
  "Message": "Product with id = 12 not found"
}

Beachten Sie, dass der HttpError in JSON in diesem Beispiel serialisiert wurde. Ein Vorteil der Verwendung von HttpError besteht darin, dass sie den gleichen Prozess der Inhaltsverhandlung und Serialisierung wie jedes andere stark typierte Modell durchläuft.

HttpError- und Modellüberprüfung

Für die Modellüberprüfung können Sie den Modellstatus an CreateErrorResponse übergeben, um die Überprüfungsfehler in die Antwort einzuschließen:

public HttpResponseMessage PostProduct(Product item)
{
    if (!ModelState.IsValid)
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
    }

    // Implementation not shown...
}

In diesem Beispiel wird möglicherweise die folgende Antwort zurückgegeben:

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Length: 320

{
  "Message": "The request is invalid.",
  "ModelState": {
    "item": [
      "Required property 'Name' not found in JSON. Path '', line 1, position 14."
    ],
    "item.Name": [
      "The Name field is required."
    ],
    "item.Price": [
      "The field Price must be between 0 and 999."
    ]
  }
}

Weitere Informationen zur Modellüberprüfung finden Sie unter Modellüberprüfung in ASP.NET Web-API.

Verwenden von HttpError mit HttpResponseException

In den vorherigen Beispielen wird eine HttpResponseMessage-Nachricht aus der Controlleraktion zurückgegeben, Sie können aber auch HttpResponseException verwenden, um einen HttpError zurückzugeben. Auf diese Weise können Sie ein stark typisiertes Modell im normalen Erfolgsfall zurückgeben, während httpError weiterhin zurückgegeben wird, wenn ein Fehler auftritt:

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        throw new HttpResponseException(
            Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
    }
    else
    {
        return item;
    }
}