Korzystam z programu ASP.NET Core do nowego projektu interfejsu API REST po wielu latach używania zwykłego interfejsu API sieci Web platformy ASP.NET. Nie widzę żadnego dobrego sposobu obsługi wyjątków w interfejsie API sieci Web platformy ASP.NET Core. Próbowałem zaimplementować filtr / atrybut obsługi wyjątków:
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
};
}
}
A oto moja rejestracja filtra startowego:
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizationFilter());
options.Filters.Add(new ErrorHandlingFilter());
});
Problem polegał na tym, że gdy w moim przypadku występuje wyjątek AuthorizationFilter
, nie jest on obsługiwany ErrorHandlingFilter
. Spodziewałem się, że zostanie tam złapany tak, jak działa ze starym interfejsem API sieci Web ASP.NET.
Jak więc wychwycić wszystkie wyjątki aplikacji, a także wyjątki z filtrów akcji?
c#
exception
asp.net-core
Andrei
źródło
źródło
UseExceptionHandler
oprogramowania pośredniego?UseExceptionHandler
oprogramowania pośredniegoOdpowiedzi:
Wyjątek Obsługa oprogramowania pośredniego
Po wielu eksperymentach z różnymi metodami obsługi wyjątków skończyłem na oprogramowaniu pośrednim. Działa najlepiej dla mojej aplikacji ASP.NET Core Web API. Obsługuje wyjątki aplikacji, a także wyjątki od filtrów akcji, a ja mam pełną kontrolę nad obsługą wyjątków i odpowiedzią HTTP. Oto mój wyjątek dotyczący oprogramowania pośredniego:
Zarejestruj go przed MVC w
Startup
klasie:Możesz dodać ślad stosu, nazwę typu wyjątku, kody błędów lub cokolwiek chcesz. Bardzo elastyczny. Oto przykład odpowiedzi wyjątku:
Rozważ wprowadzenie
IOptions<MvcJsonOptions>
tejInvoke
metody, aby następnie użyć jej podczas serializacji obiektu odpowiedzi w celu wykorzystania ustawień serializacji programu ASP.NET MVC wJsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)
celu uzyskania lepszej spójności serializacji we wszystkich punktach końcowych.Podejście 2
Istnieje inny nieoczywisty interfejs API o nazwie
UseExceptionHandler
„ok” dla prostych scenariuszy:To nie jest bardzo oczywisty, ale łatwy sposób na skonfigurowanie obsługi wyjątków. Jednak nadal wolę podejście pośrednie od niego, ponieważ mam większą kontrolę dzięki możliwości wstrzykiwania niezbędnych zależności.
źródło
app.UseMiddleware<ErrorHandlingMiddleware>();
się tuż przedtemapp.UseStaticFiles();
. Wydaje się, że wyjątek został teraz poprawnie wychwycony. To prowadzi mnie do przekonania.app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink();
Wykonaj wewnętrzne magiczne modyfikacje oprogramowania pośredniego, aby poprawnie zamówić oprogramowanie pośrednie.Najnowsze
Asp.Net Core
(przynajmniej od 2.2, prawdopodobnie wcześniej) ma wbudowane oprogramowanie pośrednie, które sprawia, że jest nieco łatwiejsze niż implementacja w zaakceptowanej odpowiedzi:Powinien zrobić prawie to samo, tylko trochę mniej kodu do napisania.
Ważne: Pamiętaj, aby dodać go przed
UseMvc
(lubUseRouting
w .Net Core 3), ponieważ kolejność jest ważna.źródło
Najlepiej jest użyć oprogramowania pośredniego, aby uzyskać rejestrowanie, którego szukasz. Chcesz umieścić wyjątek rejestrujący w jednym oprogramowaniu pośrednim, a następnie obsługiwać strony błędów wyświetlane użytkownikowi w innym oprogramowaniu pośrednim. Pozwala to na rozdzielenie logiki i jest zgodne z projektem Microsoft opracowanym z 2 komponentami oprogramowania pośredniego. Oto dobry link do dokumentacji Microsoft: Obsługa błędów w ASP.Net Core
Dla konkretnego przykładu możesz użyć jednego z rozszerzeń oprogramowania pośredniego StatusCodePage lub utworzyć własne w ten sposób .
Tutaj możesz znaleźć przykład rejestrowania wyjątków: ExceptionHandlerMiddleware.cs
Jeśli nie podoba Ci się ta konkretna implementacja, możesz także użyć oprogramowania pośredniego ELM , a oto kilka przykładów: Oprogramowanie pośrednie Elm Exception
Jeśli to nie działa na Twoje potrzeby, zawsze możesz rzucić własny komponent Middleware, patrząc na ich implementacje ExceptionHandlerMiddleware i ElmMiddleware, aby uchwycić koncepcje budowy własnego.
Ważne jest, aby dodać oprogramowanie pośredniczące do obsługi wyjątków poniżej oprogramowania pośredniego StatusCodePages, ale przede wszystkim do innych składników oprogramowania pośredniego. W ten sposób oprogramowanie pośrednie Exception przechwytuje wyjątek, rejestruje go, a następnie zezwala na przejście do oprogramowania pośredniego StatusCodePage, które wyświetli przyjazną stronę błędu dla użytkownika.
źródło
UseStatusCodePages
jest przydatne w implementacjach usług Web API. Brak widoków lub HTML, tylko odpowiedzi JSON ...Dobrze przyjęta odpowiedź bardzo mi pomogła, ale chciałem przekazać HttpStatusCode w moim oprogramowaniu pośrednim, aby zarządzać kodem błędu w czasie wykonywania.
Według tego linku mam pomysł, aby zrobić to samo. Więc połączyłem z tym Andrei Answer. Więc mój końcowy kod jest poniżej:
1. Klasa podstawowa
2. Typ klasy wyjątku niestandardowego
3. Oprogramowanie pośrednie wyjątku niestandardowego
4. Metoda rozszerzenia
5. Skonfiguruj metodę w startup.cs
Teraz moja metoda logowania w kontrolerze konta:
Powyżej możesz zobaczyć, czy nie znalazłem użytkownika, a następnie zgłaszając wyjątek HttpStatusCodeException, w którym przekazałem status HttpStatusCode.NotFound i komunikat niestandardowy
W oprogramowaniu pośrednim
zostanie wywołany blok, który przekaże kontrolę
.
Ale co, jeśli wcześniej wystąpił błąd czasu wykonywania? Do tego użyłem try catch catch, który wyrzuca wyjątek i zostanie złapany w catch (Exception wyjątekObj) i przekaże kontrolę do
metoda.
Użyłem pojedynczej klasy ErrorDetails dla zapewnienia jednolitości.
źródło
startup.cs
wvoid Configure(IapplicationBuilder app)
otrzymuję komunikat o błędzieIApplicationBuilder does not contain a definition for ConfigureCustomExceptionMiddleware
. I dodałem referencję, gdzieCustomExceptionMiddleware.cs
jest.Aby skonfigurować zachowanie obsługi wyjątków dla każdego typu wyjątku, możesz użyć oprogramowania pośredniego z pakietów NuGet:
ASP.NET Core 2.0
ASP.NET Core 2.1+
.Przykładowy kod:
źródło
Po pierwsze, dzięki Andreiowi, ponieważ swoje rozwiązanie oparłem na jego przykładzie.
Uwzględniam mój, ponieważ jest to bardziej kompletna próbka i może zaoszczędzić czytelnikom trochę czasu.
Ograniczeniem podejścia Andrei jest to, że nie obsługuje rejestrowania, przechwytywania potencjalnie użytecznych zmiennych żądań i negocjacji treści (zawsze zwróci JSON bez względu na to, czego zażądał klient - XML / zwykły tekst itp.).
Moje podejście polega na użyciu ObjectResult, który pozwala nam korzystać z funkcjonalności zapisanej w MVC.
Ten kod zapobiega również buforowaniu odpowiedzi.
Odpowiedź na błąd została ozdobiona w taki sposób, że może być serializowany przez serializator XML.
źródło
Najpierw skonfiguruj program ASP.NET Core 2,
Startup
aby ponownie uruchamiał się na stronie błędów pod kątem błędów z serwera WWW i nieobsługiwanych wyjątków.Następnie zdefiniuj typ wyjątku, który pozwoli Ci zgłaszać błędy przy użyciu kodów stanu HTTP.
Na koniec w kontrolerze strony błędu dostosuj odpowiedź na podstawie przyczyny błędu i tego, czy odpowiedź będzie widoczna bezpośrednio przez użytkownika końcowego. Ten kod zakłada, że wszystkie adresy URL interfejsu API zaczynają się od
/api/
.Program ASP.NET Core zarejestruje szczegóły błędu, za pomocą którego będziesz debugować, więc kod stanu może być wszystkim, co chcesz podać (potencjalnie niezaufanemu) requesterowi. Jeśli chcesz wyświetlić więcej informacji, możesz ulepszyć,
HttpException
aby je podać. W przypadku błędów interfejsu API można wstawić informacje o błędzie zakodowane w formacie JSON w treści komunikatu, zastępującreturn StatusCode...
je parametremreturn Json...
.źródło
użyj oprogramowania pośredniego lub IExceptionHandlerPathFeature jest w porządku. jest inny sposób eshopie
utwórz filtr wyjątków i zarejestruj go
źródło