Ich habe Bedenken hinsichtlich der Art und Weise, wie wir Fehler an den Kunden zurücksenden.
Geben wir den Fehler sofort zurück, indem wir HttpResponseException auslösen, wenn wir einen Fehler erhalten:
public void Post(Customer customer)
{
if (string.IsNullOrEmpty(customer.Name))
{
throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
}
if (customer.Accounts.Count == 0)
{
throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest)
}
}
Oder wir sammeln alle Fehler und senden sie an den Kunden zurück:
public void Post(Customer customer)
{
List<string> errors = new List<string>();
if (string.IsNullOrEmpty(customer.Name))
{
errors.Add("Customer Name cannot be empty");
}
if (customer.Accounts.Count == 0)
{
errors.Add("Customer does not have any account");
}
var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
throw new HttpResponseException(responseMessage);
}
Dies ist nur ein Beispielcode. Es spielt keine Rolle, ob es sich um Validierungsfehler oder Serverfehler handelt. Ich möchte nur die Best Practice sowie die Vor- und Nachteile der einzelnen Ansätze kennen.
c#
rest
asp.net-web-api
cuongle
quelle
quelle
ModelState
.HttpResponseException
Klasse, die zwei in Ihrem Beitrag erwähnte ParameterHttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
HttpResponseException(string, HttpStatusCode)
Antworten:
Für mich sende ich normalerweise einen zurück
HttpResponseException
und setze den Statuscode entsprechend der ausgelösten Ausnahme entsprechend. Wenn die Ausnahme schwerwiegend ist oder nicht, wird bestimmt, ob ich denHttpResponseException
sofort zurückschicke .Letztendlich ist es eine API, die Antworten und keine Ansichten zurücksendet. Ich denke, es ist in Ordnung, eine Nachricht mit der Ausnahme und dem Statuscode an den Verbraucher zurückzusenden. Ich musste derzeit keine Fehler akkumulieren und zurücksenden, da die meisten Ausnahmen normalerweise auf falsche Parameter oder Aufrufe usw. zurückzuführen sind.
Ein Beispiel in meiner App ist, dass der Client manchmal nach Daten fragt, aber keine Daten verfügbar sind. Deshalb werfe ich eine benutzerdefinierte Datei
NoDataAvailableException
und lasse sie in die Web-API-App sprudeln, wo sie dann in meinem benutzerdefinierten Filter erfasst wird, der sie zurücksendet relevante Nachricht zusammen mit dem richtigen Statuscode.Ich bin mir nicht 100% sicher, was die beste Vorgehensweise dafür ist, aber das funktioniert derzeit für mich, also mache ich das auch.
Update :
Seit ich diese Frage beantwortet habe, wurden einige Blog-Beiträge zum Thema geschrieben:
https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling
(Dieser hat einige neue Funktionen in den nächtlichen Builds) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi
Update 2
Bei der Aktualisierung unseres Fehlerbehandlungsprozesses gibt es zwei Fälle:
Bei allgemeinen Fehlern wie nicht gefunden oder ungültigen Parametern, die an eine Aktion übergeben werden, wird a zurückgegeben
HttpResponseException
, um die Verarbeitung sofort zu stoppen. Zusätzlich übergeben wir für Modellfehler in unseren Aktionen das Modellstatuswörterbuch an dieRequest.CreateErrorResponse
Erweiterung und verpacken es in aHttpResponseException
. Das Hinzufügen des Modellstatuswörterbuchs führt zu einer Liste der Modellfehler, die im Antworttext gesendet werden.Für Fehler, die in höheren Schichten auftreten, Serverfehler, lassen wir die Ausnahme in die Web-API-App sprudeln. Hier haben wir einen globalen Ausnahmefilter, der die Ausnahme betrachtet, sie mit ELMAH protokolliert und versucht, das richtige HTTP festzulegen Statuscode und eine relevante freundliche Fehlermeldung als Körper wieder in a
HttpResponseException
. Für Ausnahmen, die wir nicht erwarten, erhält der Client den Standardfehler von 500 internen Servern, aber aus Sicherheitsgründen eine generische Nachricht.Update 3
Kürzlich haben wir nach dem Aufrufen von Web API 2 zum Zurücksenden allgemeiner Fehler die IHttpActionResult- Schnittstelle verwendet, insbesondere die im
System.Web.Http.Results
Namespace integrierten Klassen wie NotFound, BadRequest, wenn sie passen, wenn wir sie beispielsweise nicht erweitern ein NotFound-Ergebnis mit einer Antwortnachricht:quelle
ASP.NET Web API 2 hat es wirklich vereinfacht. Zum Beispiel der folgende Code:
Gibt den folgenden Inhalt an den Browser zurück, wenn das Element nicht gefunden wird:
Vorschlag: Wirf keinen HTTP-Fehler 500 aus, es sei denn, es liegt ein katastrophaler Fehler vor (z. B. WCF-Fehlerausnahme). Wählen Sie einen geeigneten HTTP-Statuscode aus, der den Status Ihrer Daten darstellt. (Siehe den Apigee-Link unten.)
Links:
quelle
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
Was ist der Unterschied zwischenCreateResponse
undCreateErrorResponse
using System.Net.Http;
dieCreateResponse()
Erweiterungsmethode anzeigen.Es sieht so aus, als hätten Sie mehr Probleme mit der Validierung als mit Fehlern / Ausnahmen, daher werde ich zu beiden etwas sagen.
Validierung
Controller-Aktionen sollten im Allgemeinen Eingabemodelle verwenden, bei denen die Validierung direkt im Modell deklariert ist.
Anschließend können Sie eine verwenden
ActionFilter
, die automatisch Validierungsnachrichten an den Client zurücksendet.Weitere Informationen hierzu finden Sie unter http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
Fehlerbehandlung
Am besten senden Sie eine Nachricht an den Client zurück, die die aufgetretene Ausnahme darstellt (mit dem entsprechenden Statuscode).
Standardmäßig müssen Sie verwenden,
Request.CreateErrorResponse(HttpStatusCode, message)
wenn Sie eine Nachricht angeben möchten. Dies bindet den Code jedoch an dasRequest
Objekt, was Sie nicht tun müssen.Normalerweise erstelle ich meine eigene Art von "sicherer" Ausnahme, von der ich erwarte, dass der Client weiß, wie er alle anderen mit einem generischen 500-Fehler behandelt und umschließt.
Die Verwendung eines Aktionsfilters zur Behandlung der Ausnahmen würde folgendermaßen aussehen:
Dann können Sie es global registrieren.
Dies ist mein benutzerdefinierter Ausnahmetyp.
Eine Beispielausnahme, die meine API auslösen kann.
quelle
var exception = context.Exception as WebException;
, was ein Tippfehler war, sollte es gewesen seinApiException
Sie können eine HttpResponseException auslösen
quelle
Für Web API 2 geben meine Methoden konsistent IHttpActionResult zurück, also verwende ich ...
quelle
System.Net.Http
Wenn Sie ASP.NET Web API 2 verwenden, verwenden Sie am einfachsten die ApiController-Kurzmethode. Dies führt zu einem BadRequestResult.
quelle
return BadRequest(ModelState);
Sie können einen benutzerdefinierten ActionFilter in Web Api verwenden, um das Modell zu überprüfen
}}
Registrieren Sie die CustomAttribute-Klasse in webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());
quelle
Aufbauend auf
Manish Jain
der Antwort (die für die Web-API 2 gedacht ist, die die Dinge vereinfacht):1) Verwenden Sie Validierungsstrukturen, um so viele Validierungsfehler wie möglich zu beantworten. Diese Strukturen können auch verwendet werden, um auf Anfragen aus Formularen zu antworten.
2) Die Serviceschicht gibt
ValidationResult
s zurück, unabhängig davon, ob der Vorgang erfolgreich ist oder nicht. Z.B:3) Der API-Controller erstellt die Antwort basierend auf dem Ergebnis der Servicefunktion
Eine Möglichkeit besteht darin, praktisch alle Parameter als optional festzulegen und eine benutzerdefinierte Validierung durchzuführen, die eine aussagekräftigere Antwort liefert. Außerdem achte ich darauf, dass keine Ausnahme über die Servicegrenze hinausgeht.
quelle
Verwenden Sie die integrierte Methode "InternalServerError" (verfügbar in ApiController):
quelle
Nur um den aktuellen Status von ASP.NET WebAPI zu aktualisieren. Die Schnittstelle wird jetzt aufgerufen
IActionResult
und die Implementierung hat sich nicht wesentlich geändert:quelle
Bei Fehlern, bei denen modelstate.isvalid false ist, sende ich den Fehler im Allgemeinen so, wie er vom Code ausgelöst wird. Es ist leicht zu verstehen für den Entwickler, der meinen Service in Anspruch nimmt. Normalerweise sende ich das Ergebnis mit dem folgenden Code.
Dadurch wird der Fehler im folgenden Format an den Client gesendet. Dies ist im Grunde eine Liste von Fehlern:
quelle