Hintergrund
Ich entwickle eine API-Service-Schicht für einen Client und wurde aufgefordert, alle Fehler global abzufangen und zu protokollieren.
Während also so etwas wie ein unbekannter Endpunkt (oder eine unbekannte Aktion) einfach zu handhaben ist, verwenden Sie ELMAH oder fügen Sie Folgendes hinzu Global.asax
:
protected void Application_Error()
{
Exception unhandledException = Server.GetLastError();
//do more stuff
}
. . Nicht behandelte Fehler, die nicht mit dem Routing zusammenhängen, werden nicht protokolliert. Beispielsweise:
public class ReportController : ApiController
{
public int test()
{
var foo = Convert.ToInt32("a");//Will throw error but isn't logged!!
return foo;
}
}
Ich habe auch versucht, das [HandleError]
Attribut global festzulegen, indem ich diesen Filter registriert habe:
filters.Add(new HandleErrorAttribute());
Das protokolliert aber auch nicht alle Fehler.
Problem / Frage
Wie fange ich Fehler ab, wie sie durch den /test
obigen Aufruf generiert wurden, damit ich sie protokollieren kann? Es scheint, dass diese Antwort offensichtlich sein sollte, aber ich habe alles versucht, was mir bisher einfällt.
Im Idealfall möchte ich der Fehlerprotokollierung einige Dinge hinzufügen, z. B. die IP-Adresse des anfordernden Benutzers, Datum, Uhrzeit usw. Ich möchte auch in der Lage sein, dem Support-Personal automatisch eine E-Mail zu senden, wenn ein Fehler auftritt. All dies kann ich tun, wenn ich diese Fehler nur abfangen kann, wenn sie auftreten!
AUFGELÖST!
Dank Darin Dimitrov, dessen Antwort ich akzeptierte, habe ich das herausgefunden. WebAPI behandelt Fehler nicht wie ein normaler MVC-Controller.
Folgendes hat funktioniert:
1) Fügen Sie Ihrem Namespace einen benutzerdefinierten Filter hinzu:
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is BusinessException)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message),
ReasonPhrase = "Exception"
});
}
//Log Critical errors
Debug.WriteLine(context.Exception);
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("An error occurred, please try again or contact the administrator."),
ReasonPhrase = "Critical Exception"
});
}
}
2) Registrieren Sie nun den Filter global in der WebApiConfig- Klasse:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
config.Filters.Add(new ExceptionHandlingAttribute());
}
}
ODER Sie können die Registrierung überspringen und einfach einen einzelnen Controller mit dem [ExceptionHandling]
Attribut dekorieren .
quelle
Antworten:
Wenn Ihre Web-API in einer ASP.NET-Anwendung gehostet wird, wird dasApplication_Error
Ereignis für alle nicht behandelten Ausnahmen in Ihrem Code aufgerufen, einschließlich derjenigen in der von Ihnen gezeigten Testaktion. Sie müssen diese Ausnahme also nur innerhalb des Application_Error-Ereignisses behandeln. In dem Beispielcode, den Sie gezeigt haben, behandeln Sie nur Ausnahmen vom Typ,HttpException
was beimConvert.ToInt32("a")
Code offensichtlich nicht der Fall ist . Stellen Sie also sicher, dass Sie alle darin enthaltenen Ausnahmen protokollieren und behandeln:Die Ausnahmebehandlung in der Web-API kann auf verschiedenen Ebenen erfolgen. Hier
detailed article
erklären Sie die verschiedenen Möglichkeiten:Benutzerdefiniertes Ausnahmefilterattribut, das als globaler Ausnahmefilter registriert werden kann
Benutzerdefinierter Aktionsaufrufer
quelle
Application_Error
Ereignis nicht abgefangen wird , bedeutet dies, dass ein anderer Code sie zuvor verwendet. Zum Beispiel könnten Sie einige benutzerdefinierte HandleErrorAttributes, benutzerdefinierte Module, ... haben. Es gibt Unmengen anderer Stellen, an denen Ausnahmen abgefangen und behandelt werden könnten. Der beste Ort dafür ist jedoch das Application_Error-Ereignis, da dort alle nicht behandelten Ausnahmen enden./test
passiert , das Beispiel wird nicht getroffen. Ich habe einen Haltepunkt in die erste Zeile gesetzt (Exception unhandledException = . . .
), kann diesen Haltepunkt jedoch im/test
Szenario nicht erreichen. Wenn ich jedoch eine falsche URL eingebe, wird der Haltepunkt erreicht.Application_Error
Ereignis ist nicht der richtige Ort, um Ausnahmen für die Web-API zu behandeln, da es nicht in allen Fällen ausgelöst wird. Ich habe einen sehr detaillierten Artikel gefunden, der die verschiedenen Möglichkeiten erklärt, dies zu erreichen: weblogs.asp.net/fredriknormen/archive/2012/06/11/…Als Ergänzung zu früheren Antworten.
Gestern wurde die ASP.NET Web API 2.1 offiziell veröffentlicht .
Es bietet eine weitere Möglichkeit, Ausnahmen global zu behandeln.
Die Details sind im Beispiel angegeben .
Kurz gesagt, Sie fügen globale Ausnahmeprotokollierer und / oder einen globalen Ausnahmebehandler hinzu (nur einen).
Sie fügen sie der Konfiguration hinzu:
Und ihre Erkenntnis:
quelle
Warum neu werfen usw.? Dies funktioniert und der Servicerückgabestatus 500 usw.
quelle
Haben Sie darüber nachgedacht, so etwas wie einen Handle-Error-Action-Filter wie zu machen?
Sie können auch eine benutzerdefinierte Version erstellen,
[HandleError]
mit der Sie Fehlerinformationen und alle anderen zu protokollierenden Details schreiben könnenquelle
Wickeln Sie das Ganze in einen Versuch / Fang ein, protokollieren Sie die nicht behandelte Ausnahme und geben Sie sie dann weiter. Es sei denn, es gibt eine bessere integrierte Möglichkeit, dies zu tun.
Hier ist eine Referenz Ausnahmen von Catch All (behandelt oder nicht behandelt)
(edit: oh API)
quelle