Ich verwende ASP.NET Core für mein neues REST-API-Projekt, nachdem ich viele Jahre lang die reguläre ASP.NET-Web-API verwendet habe. Ich sehe keine gute Möglichkeit, Ausnahmen in der ASP.NET Core-Web-API zu behandeln. Ich habe versucht, Ausnahmebehandlungsfilter / -attribut zu implementieren:
public class ErrorHandlingFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
HandleExceptionAsync(context);
context.ExceptionHandled = true;
}
private static void HandleExceptionAsync(ExceptionContext context)
{
var exception = context.Exception;
if (exception is MyNotFoundException)
SetExceptionResult(context, exception, HttpStatusCode.NotFound);
else if (exception is MyUnauthorizedException)
SetExceptionResult(context, exception, HttpStatusCode.Unauthorized);
else if (exception is MyException)
SetExceptionResult(context, exception, HttpStatusCode.BadRequest);
else
SetExceptionResult(context, exception, HttpStatusCode.InternalServerError);
}
private static void SetExceptionResult(
ExceptionContext context,
Exception exception,
HttpStatusCode code)
{
context.Result = new JsonResult(new ApiResponse(exception))
{
StatusCode = (int)code
};
}
}
Und hier ist meine Registrierung für den Startfilter:
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizationFilter());
options.Filters.Add(new ErrorHandlingFilter());
});
Das Problem, das ich hatte, ist, dass wenn eine Ausnahme in meinem auftritt, AuthorizationFilter
diese nicht von behandelt wird ErrorHandlingFilter
. Ich hatte erwartet, dass es dort abgefangen wird, genau wie es mit der alten ASP.NET-Web-API funktioniert.
Wie kann ich also alle Anwendungsausnahmen sowie Ausnahmen von Aktionsfiltern abfangen?
c#
exception
asp.net-core
Andrei
quelle
quelle
UseExceptionHandler
Middleware ausprobiert ?UseExceptionHandler
MiddlewareAntworten:
Ausnahmebehandlung Middleware
Nach vielen Experimenten mit verschiedenen Ausnahmehandlungsansätzen habe ich Middleware verwendet. Für meine ASP.NET Core Web API-Anwendung hat es am besten funktioniert. Es behandelt Anwendungsausnahmen sowie Ausnahmen von Aktionsfiltern und ich habe die volle Kontrolle über die Ausnahmebehandlung und die HTTP-Antwort. Hier ist meine Ausnahmebehandlung für Middleware:
Registrieren Sie es vor MVC in der
Startup
Klasse:Sie können Stack-Trace, Namen des Ausnahmetyps, Fehlercodes oder alles, was Sie möchten, hinzufügen. Sehr flexibel. Hier ist ein Beispiel für eine Ausnahmeantwort:
Erwägen Sie
IOptions<MvcJsonOptions>
, dieInvoke
Methode zu injizieren , um sie dann zu verwenden, wenn Sie das Antwortobjekt serialisieren, um die Serialisierungseinstellungen von ASP.NET MVCJsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)
für eine bessere Serialisierungskonsistenz über alle Endpunkte hinweg zu verwenden.Ansatz 2
Es gibt eine andere nicht offensichtliche API namens
UseExceptionHandler
"ok" für einfache Szenarien:Dies ist keine sehr offensichtliche, aber einfache Möglichkeit, die Ausnahmebehandlung einzurichten. Ich bevorzuge jedoch immer noch den Middleware-Ansatz, da ich mehr Kontrolle über die Möglichkeit habe, die erforderlichen Abhängigkeiten einzufügen.
quelle
app.UseMiddleware<ErrorHandlingMiddleware>();
kurz zuvor umgezogenapp.UseStaticFiles();
. Die Ausnahme scheint jetzt richtig abgefangen zu sein. Dies lässt mich glauben, dassapp.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink();
Sie einige interne magische Middleware-Hackerarbeiten durchführen müssen, um die Middleware-Bestellung richtig zu machen.Neueste
Asp.Net Core
(mindestens ab 2.2, wahrscheinlich früher) verfügt über eine integrierte Middleware, die es im Vergleich zur Implementierung in der akzeptierten Antwort etwas einfacher macht:Es sollte ziemlich genau das Gleiche tun, nur ein bisschen weniger Code zum Schreiben.
Wichtig: Denken Sie daran, es vorher
UseMvc
(oderUseRouting
in .Net Core 3) hinzuzufügen, da die Reihenfolge wichtig ist.quelle
Am besten verwenden Sie Middleware, um die gewünschte Protokollierung zu erreichen. Sie möchten Ihre Ausnahmeprotokollierung in einer Middleware ablegen und dann Ihre Fehlerseiten behandeln, die dem Benutzer in einer anderen Middleware angezeigt werden. Dies ermöglicht eine Trennung der Logik und folgt dem Design, das Microsoft mit den beiden Middleware-Komponenten festgelegt hat. Hier ist ein guter Link zur Dokumentation von Microsoft: Fehlerbehandlung in ASP.Net Core
Für Ihr spezielles Beispiel möchten Sie möglicherweise eine der Erweiterungen in der StatusCodePage-Middleware verwenden oder Ihre eigene auf diese Weise rollen .
Ein Beispiel für die Protokollierung von Ausnahmen finden Sie hier: ExceptionHandlerMiddleware.cs
Wenn Ihnen diese spezielle Implementierung nicht gefällt, können Sie auch ELM Middleware verwenden . Hier einige Beispiele: Elm Exception Middleware
Wenn dies für Ihre Anforderungen nicht funktioniert, können Sie jederzeit Ihre eigene Middleware-Komponente rollen, indem Sie sich deren Implementierungen der ExceptionHandlerMiddleware und der ElmMiddleware ansehen, um die Konzepte zum Erstellen Ihrer eigenen zu verstehen.
Es ist wichtig, die Ausnahmebehandlungs-Middleware unterhalb der StatusCodePages-Middleware, aber vor allem Ihrer anderen Middleware-Komponenten hinzuzufügen. Auf diese Weise erfasst Ihre Exception-Middleware die Ausnahme, protokolliert sie und lässt die Anforderung dann zur StatusCodePage-Middleware übergehen, die dem Benutzer die freundliche Fehlerseite anzeigt.
quelle
UseStatusCodePages
bei der Implementierung von Web-API-Diensten von Nutzen ist. Keine Ansichten oder HTML überhaupt, nur JSON-Antworten ...Eine gut akzeptierte Antwort hat mir sehr geholfen, aber ich wollte HttpStatusCode in meiner Middleware übergeben, um den Fehlerstatuscode zur Laufzeit zu verwalten.
Laut diesem Link habe ich eine Idee, dasselbe zu tun. Also habe ich die Andrei-Antwort damit zusammengeführt. Mein endgültiger Code ist also unten:
1. Basisklasse
2. Benutzerdefinierter Ausnahmeklassentyp
3. Benutzerdefinierte Ausnahme Middleware
4. Verlängerungsmethode
5. Konfigurieren Sie die Methode in startup.cs
Nun meine Anmeldemethode im Account Controller:
Oben können Sie sehen, ob ich den Benutzer nicht gefunden habe, und dann die HttpStatusCodeException auslösen, in der ich den Status HttpStatusCode.NotFound und eine benutzerdefinierte Nachricht
in Middleware übergeben habe
blockiert wird aufgerufen, wodurch die Kontrolle an übergeben wird
.
Aber was ist, wenn ich vorher einen Laufzeitfehler habe? Dafür habe ich try catch block verwendet, der eine Ausnahme auslöst und im catch-Block (Exception exceptionObj) abgefangen wird und die Kontrolle an übergibt
Methode.
Ich habe eine einzelne ErrorDetails-Klasse verwendet, um die Einheitlichkeit zu gewährleisten.
quelle
startup.cs
invoid Configure(IapplicationBuilder app)
einen FehlerIApplicationBuilder does not contain a definition for ConfigureCustomExceptionMiddleware
. Und ich habe die Referenz hinzugefügt, woCustomExceptionMiddleware.cs
ist.Um das Verhalten bei der Ausnahmebehandlung pro Ausnahmetyp zu konfigurieren, können Sie Middleware aus NuGet-Paketen verwenden:
ASP.NET Core 2.0
ASP.NET Core 2.1+
.Codebeispiel:
quelle
Erstens danke ich Andrei, der meine Lösung auf sein Beispiel gestützt hat.
Ich schließe meine ein, da es sich um ein vollständigeres Beispiel handelt und den Lesern möglicherweise Zeit spart.
Die Einschränkung des Ansatzes von Andrei besteht darin, dass die Protokollierung, die Erfassung potenziell nützlicher Anforderungsvariablen und die Aushandlung von Inhalten nicht behandelt werden (JSON wird immer zurückgegeben, unabhängig davon, was der Client angefordert hat - XML / Nur-Text usw.).
Mein Ansatz ist die Verwendung eines ObjectResult, mit dem wir die in MVC integrierte Funktionalität verwenden können.
Dieser Code verhindert auch das Zwischenspeichern der Antwort.
Die Fehlerantwort wurde so dekoriert, dass sie vom XML-Serializer serialisiert werden kann.
quelle
Konfigurieren Sie zunächst ASP.NET Core 2 so
Startup
, dass es bei Fehlern vom Webserver und nicht behandelten Ausnahmen erneut auf einer Fehlerseite ausgeführt wird.Definieren Sie als Nächstes einen Ausnahmetyp, mit dem Sie Fehler mit HTTP-Statuscodes auslösen können.
Passen Sie schließlich in Ihrem Controller für die Fehlerseite die Antwort basierend auf dem Grund für den Fehler und der Frage an, ob die Antwort direkt von einem Endbenutzer angezeigt wird. Dieser Code setzt voraus, dass alle API-URLs mit beginnen
/api/
.ASP.NET Core protokolliert die Fehlerdetails, mit denen Sie debuggen können, sodass Sie möglicherweise nur einen Statuscode für einen (möglicherweise nicht vertrauenswürdigen) Anforderer bereitstellen möchten. Wenn Sie weitere Informationen anzeigen möchten, können Sie diese erweitern
HttpException
, um sie bereitzustellen. Für API - Fehler, können Sie setzen JSON-kodierte Fehlerinformationen in dem Nachrichtentext durch den Ersatzreturn StatusCode...
mitreturn Json...
.quelle
Verwenden Sie Middleware oder IExceptionHandlerPathFeature ist in Ordnung. Es gibt einen anderen Weg im Eshop
Erstellen Sie einen Ausnahmefilter und registrieren Sie ihn
quelle