tło
Opracowuję warstwę usług API dla klienta i poproszono mnie o globalne wyłapywanie i rejestrowanie wszystkich błędów.
Tak więc, chociaż coś takiego jak nieznany punkt końcowy (lub akcja) można łatwo obsłużyć za pomocą ELMAH lub dodając coś takiego do Global.asax
:
protected void Application_Error()
{
Exception unhandledException = Server.GetLastError();
//do more stuff
}
. . Nieobsługiwane błędy, które nie są związane z routingiem, nie są rejestrowane. Na przykład:
public class ReportController : ApiController
{
public int test()
{
var foo = Convert.ToInt32("a");//Will throw error but isn't logged!!
return foo;
}
}
Próbowałem również ustawić [HandleError]
atrybut globalnie, rejestrując ten filtr:
filters.Add(new HandleErrorAttribute());
Ale to również nie rejestruje wszystkich błędów.
Problem / pytanie
Jak przechwycić błędy, takie jak ten wygenerowany przez wywołanie /test
powyżej, aby móc je zarejestrować? Wydaje się, że ta odpowiedź powinna być oczywista, ale próbowałem wszystkiego, o czym przyszło mi do głowy.
Najlepiej byłoby dodać kilka rzeczy do rejestrowania błędów, takich jak adres IP użytkownika żądającego, data, godzina i tak dalej. Chcę również mieć możliwość automatycznego wysyłania e-maili do personelu pomocniczego w przypadku napotkania błędu. Wszystko to mogę zrobić, jeśli tylko zdołam przechwycić te błędy, gdy się pojawią!
ZDECYDOWANY!
Dzięki Darinowi Dimitrovowi, którego odpowiedź przyjąłem, zrozumiałem. Interfejs WebAPI nie obsługuje błędów w taki sam sposób, jak zwykły kontroler MVC.
Oto, co zadziałało:
1) Dodaj niestandardowy filtr do swojej przestrzeni nazw:
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) Teraz zarejestruj filtr globalnie w klasie WebApiConfig :
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());
}
}
LUB możesz pominąć rejestrację i po prostu ozdobić pojedynczy kontroler [ExceptionHandling]
atrybutem.
źródło
Odpowiedzi:
Jeśli interfejs API sieci Web jest hostowany w aplikacji ASP.NET,Application_Error
zdarzenie zostanie wywołane dla wszystkich nieobsłużonych wyjątków w kodzie, w tym wyjątków w pokazanej akcji testowej. Więc wszystko, co musisz zrobić, to obsłużyć ten wyjątek wewnątrz zdarzenia Application_Error. W przykładowym kodzie, który pokazałeś, obsługujesz tylko wyjątek typu,HttpException
który oczywiście nie ma miejsca w przypadkuConvert.ToInt32("a")
kodu. Więc upewnij się, że logujesz i obsługujesz tam wszystkie wyjątki:Obsługa wyjątków w internetowym interfejsie API może odbywać się na różnych poziomach. Oto
detailed article
wyjaśnienie różnych możliwości:niestandardowy atrybut filtru wyjątków, który można zarejestrować jako globalny filtr wyjątków
wywołujący akcję niestandardową
źródło
Application_Error
zdarzeniu, oznacza to, że jakiś inny kod używa go wcześniej. Na przykład możesz mieć niestandardowe HandleErrorAttributes, niestandardowe moduły, ... Istnieją miliardy innych miejsc, w których wyjątki mogą być przechwytywane i obsługiwane. Ale najlepszym miejscem do tego jest zdarzenie Application_Error, ponieważ tam kończą się wszystkie nieobsłużone wyjątki./test
przykład nie został trafiony. Umieściłem punkt przerwania w pierwszej linii (Exception unhandledException = . . .
), ale nie mogę go osiągnąć w/test
scenariuszu. Jeśli jednak wstawię fałszywy adres URL, zostanie osiągnięty punkt przerwania.Application_Error
Zdarzenie nie jest właściwe miejsce, aby obsłużyć wyjątki dla Web API, ponieważ nie zostanie uruchomiony we wszystkich przypadkach. Znalazłem bardzo szczegółowy artykuł wyjaśniający różne możliwości osiągnięcia tego celu: weblogs.asp.net/fredriknormen/archive/2012/06/11/…Jako dodatek do poprzednich odpowiedzi.
Wczoraj został oficjalnie wydany ASP.NET Web API 2.1 .
Daje kolejną możliwość obsługi wyjątków na całym świecie.
Szczegóły podano w próbce .
Krótko mówiąc, dodajesz globalne rejestratory wyjątków i / lub globalną obsługę wyjątków (tylko jeden).
Dodajesz je do konfiguracji:
I ich realizacja:
źródło
Po co wrzucać ponownie itp.? To działa i sprawi, że usługa zostanie zwrócona o statusie 500 itd
źródło
czy myślałeś o zrobieniu czegoś w rodzaju filtru działania błędu obsługi, takiego jak
możesz również utworzyć niestandardową wersję programu, za
[HandleError]
pomocą której możesz zapisywać informacje o błędach i wszystkie inne szczegóły do logowaniaźródło
Zawiń całość w try / catch i zarejestruj nieobsługiwany wyjątek, a następnie przekaż go dalej. Chyba że istnieje lepszy wbudowany sposób, aby to zrobić.
Oto odniesienie do wszystkich wyjątków (obsłużonych lub nieobsługiwanych)
(edytuj: oh API)
źródło