Jakie są ostateczne wytyczne dotyczące niestandardowej obsługi błędów w ASP.NET MVC 3?

44

Proces wykonywania niestandardowej obsługi błędów w ASP.NET MVC (w tym przypadku 3) wydaje się niezwykle zaniedbany. Przeczytałem różne pytania i odpowiedzi tutaj, w Internecie, na stronach pomocy dla różnych narzędzi (takich jak Elmah), ale wydaje mi się, że znalazłem się w pełnym kręgu i wciąż nie mam najlepszego rozwiązania. Z twoją pomocą możemy ustalić nowe standardowe podejście do obsługi błędów. Chciałbym uprościć sprawę i nie przesadzać z tym.

Oto moje cele:

W przypadku błędów / wyjątków serwera:

  1. Wyświetl informacje debugowania w dev
  2. Wyświetl przyjazną stronę błędu w produkcji
  3. Zaloguj błędy i wyślij je e-mailem do administratora w produkcji
  4. Zwróć 500 Kod stanu HTTP

W przypadku błędów 404 nie znaleziono:

  1. Wyświetl przyjazną stronę błędu
  2. Zaloguj błędy i wyślij je e-mailem do administratora w produkcji
  3. Zwróć kod stanu HTTP 404

Czy istnieje sposób na osiągnięcie tych celów dzięki ASP.NET MVC?

RyanW
źródło
2
Chciałbym przenieść to pytanie Z POWROTEM do SO, aby uzyskać więcej odpowiedzi. Szukam zakodowanych odpowiedzi.
Shawn Mclean
@Shawn To mało prawdopodobne. Pytanie dotyczy bardziej tematu niż SO i ma akceptowaną odpowiedź. Pytania z reguły również nie podlegają migracji z przyczyn technicznych. Jeśli potrzebujesz pomocy w kodowaniu określonego podejścia do obsługi błędów, otwórz nowe pytanie na StackOverflow. W przeciwnym razie „zakodowane odpowiedzi” mogą być zbyt szerokim kryterium, aby były użyteczne lub odpowiedzialne. Wreszcie, najlepszym sposobem na zwrócenie uwagi moderatora na pytanie jest jego oflagowanie. Twój komentarz tutaj prawdopodobnie nie zostałby zauważony, gdyby nie zadziałał auto-flag, zwiększając liczbę komentarzy o ponad 20.
Adam Lear
Kiedyś było tu około 10 komentarzy, gdzie oni wszyscy poszli?
RyanW,
Znalazłem rozwiązanie, które spełnia twoje cele. Mam to jako kolejną odpowiedź na SO: stackoverflow.com/questions/6508415/…
Jesse Webb
1
@AnnaLear Zgadzam się z Shawnem. Znalazłem tę stronę tylko przez Google. Zauważ, że prawie wszystkie poniższe odpowiedzi zawierają linki POWRÓT do przepełnienia stosu. Dla mnie to mówi dużo, ponieważ przede wszystkim powinno być tam pozostawione.
Rebecca

Odpowiedzi:

23

Podzielę się sposobem, w jaki to skończyłem, to było częścią pierwotnego pytania.

Po pierwsze, problemy, które napotkałem:

  1. Gdy customErrors jest włączony (tj. Produkcyjny), globalny HandleErroratrybut połyka wyjątki i renderuje widok błędu, ale wtedy nie można go zalogować za pomocą narzędzia dodatkowego, takiego jak elmah, ponieważ elmah nigdy go nie widzi. Przypuszczam, że możesz zalogować się w swoim widoku, ale wydaje się to błędne. Globalny atrybut HandleError pojawia się jako nowy w szablonie projektu Visual Studio MVC 3 RTM.

  2. customErrors z adresami URL dla punktów końcowych MVC zwraca 302 kody stanu. Istnieje właściwość redirectmode, ale nie można dopasować adresów URL mvc w customErrors i użyć trybu ResponseRewrite. ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. Całkowite unikanie niestandardowych błędów i obsługa wszystkich niestandardowych aplikacji prowadzi do dużej złożoności, IMO. (Ujrzałem to: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095 , ale nie było to właściwe dla naszego projektu)

Moje rozwiązanie

Całkowicie usunąłem MVC z równania. Usunąłem HandleErrorAttributeglobalny filtr w global.asax i całkowicie skoncentrować się na konfiguracji CustomErrors, przenosząc go do używania WebForm przekierowania i zmiany do redirectmode aby ResponseRewritew celu uniknięcia 302 kody odpowiedzi HTTP.

<customErrors mode="On" defaultRedirect="/Error.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="/NotFound.aspx" />
</customErrors>

Następnie w NotFound.aspxzdarzeniu page_load ustaw wartość Response.StatusCode404, aw Error.aspx ustaw kod 500.

Wyniki:

Cele dla obu zostały osiągnięte dzięki dziennikom Elmah, przyjaznej stronie błędów i kodowi stanu z jednym wierszem kodu na końcu kodu. Nie robimy tego w „MVC Way”, jak to robi wcześniejsze rozwiązanie, ale nie mam nic przeciwko, jeśli są to dwie linie kodu.

RyanW
źródło
5

Myślę, że MVC, ASP i twoja ulubiona struktura rejestrowania / obsługi wyjątków może całkiem dobrze poradzić sobie z twoimi celami. Zarówno ELMAH, jak i biblioteka Enterprise Library zapewniają łatwą w obsłudze obsługę wyjątków i rejestrowanie, więc wybierz swoją ulubioną. Nie będę tutaj omawiał zalet i wad każdego z nich.

UWAGA: nie można wyświetlić przyjaznej strony błędu ORAZ zwrócić HTTP 404 lub 500, jak sugeruje pytanie. Po zwróceniu przyjaznej strony błędu kod HTTP zwrócony do przeglądarki to 302. Jest to przekierowanie do przyjaznej strony błędu.

Przyjazne strony błędów

Wygląda na to, że możesz osiągnąć swoje cele dzięki dobrze zaprojektowanym ustawieniom web.config, które były częścią ASP.net od pewnego czasu. Wspominasz o pokazywaniu informacji debugowania w fazie projektowania i wyświetlaniu przyjaznych stron w produkcji. W tym celu możesz użyć sekcji niestandardowych błędów pliku web.config (Ustaw CustomErrors = „Wyłącz”, aby wyświetlić informacje debugowania). Zakładam, że znasz atrybut CustomErrors, jeśli nie przeczytaj tego:

http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx

Jeśli potrzebujesz większej szczegółowości kontroli nad wyświetlanymi widokami błędów, użyj atrybutu HandleError MVC. W ten sposób możesz wybrać różne widoki błędów dla każdej akcji / kontrolera.

http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx

Rejestrowanie wyjątków

Wygląda na to, że chcesz reagować na wszystkie wyjątki w ten sam sposób („Rejestruj błędy i wysyłaj je e-mailem do administratora w produkcji”). W takim przypadku najprostszą opcją jest dodanie kodu

Błąd_aplikacji (nadawca obiektu, EventArgs e)

w twoim global.asax. W tym miejscu możesz przejść do wybranej struktury rejestrowania.

Jeśli chcesz mieć większą kontrolę nad rejestrowaniem / obsługą wyjątków, możesz podklasować HandleErrorAttribute i przesłonić

OnException(System.Web.Mvc.ExceptionContext filterContext)

jest to kolejne miejsce, w którym możesz przejść do wybranej struktury rejestrowania.

https://stackoverflow.com/questions/183316/asp-net-mvc-handleerror

Daje to większą kontrolę niż technika Application_Error wspomniana powyżej.

Zasadniczo MVC zapewnia dużą kontrolę nad sposobem obsługi błędów. Jeśli nie potrzebujesz tej kontroli, możesz powrócić do metod ASP.net, takich jak definiowanie stron błędów w pliku web.config.

Nixon
źródło
Dziękuję bardzo za dodanie swoich przemyśleń. Myślę, że kod stanu 302 jest kiepskim wyborem projektowym przez oryginalny zespół ASP.NET. Zajmę się tym również w moich odpowiedziach, istnieją pewne opcje, aby to zrobić. Wygląda na to, że niektórzy w świecie MVC całkowicie porzucają niestandardowe błędy i obsługują to wszystko w aplikacji, aby zwiększyć możliwości ponownego użycia i mieć większą kontrolę, jak wskazałeś. Ale miałem ograniczony sukces we wdrażaniu tych i dodawałem dużo kodu, który wydawał się lepszy. Więcej w moich odpowiedziach poniżej.
Wolę przesłonić metodę OnException do rejestrowania, w ten sposób wiem, że mogę zalogować wszystko, nawet błąd pojawiający się w wywołaniu Ajax, które, jak się okazuje, nie wyzwoli Twojego błędu aplikacji.
Alicia,
@Alicia pełny przykładowy kod?
Kiquenet,