2011-09-06 15 views
6

Chcę rzucić wyjątek, ale z niestandardowym komunikatem i pozostałym stosem śledzenia również. Przejrzałem różne wątki.Zgłasza wyjątek, ale kontynuuje śledzenie stosu.

catch (Exception ex) 
{ 
throw; // Message is read only but stacktrace persist 
throw ex; // Message is readonly and strack trace also blows .. worst! 
throw new CustomException("My exception");// Message can be overridden but stacktrace lost 
throw new CustomException("My message",ex);// same as above. However if this constructor in exception class calls same constructor of base class then .. see below 
} 

Kiedy ostatni appraoch jest używany (z konstruktora zwyczaj Wyjątek wywołujący konstruktor klasy bazowej), wyjście na ekran śmierci jest coś takiego:

**The remote server returned an error: (401) Unauthorized.** 

[WebException: The remote server returned an error: (401) Unauthorized.] 
original stack trace 

[NewException: newMessage] 
New Stack Trace 

Dobrą rzeczą jest to wszystko jest tam na ekranie. Ale na górze chcę, aby mój wyjątek był wyświetlany, to znaczy "nowa wiadomość", a nie oryginalna wiadomość.

Stąd pogodzenie się z moim pytaniem: W JAKI SPOSÓB mogę wyświetlić na ekranie śmierci oryginalny ślad stosu, ale z niestandardowym komunikatem błędu?

+1

Jest to serwis internetowy powrocie wyjątek? – Oded

+0

W moim przykładzie jest to rzeczywiście połączenie z serwisem internetowym. Jednak nieistotne jest, że wyjątek mógł być podobny do DivisionByZero lub sqlException itp. Pomysł polega na poinformowaniu użytkownika o oryginalnym śladzie stosu, ale programista również dostosowuje domyślny komunikat wyjątku do bardziej pomocnego. – helloworld

+0

Nie, nie jest bez znaczenia. Struktury Webservice mają własne pomysły na wyjątki. –

Odpowiedz

8
throw new CustomException("My message",ex);// same as above (... stacktrace lost) 

Twój wniosek w komentarzach jest błędny przy ostatnim. Stacktrace jest utrzymywany w wewnętrznym wyjątku. Standardowe raportowanie (w tym Exception.ToString()) spowoduje zgłoszenie pełnego stosu. To właśnie widzisz, gdy konstruktor ma rację. (Zawsze wywołaj prawidłowy ctor bazowy!).

Ale nie rozpoznaję [WebException]. W WCF trzeba

<serviceDebug includeExceptionDetailInFaults="true"/> 

Chyba środowisko Web ma podobną funkcję tłumienia informacje o błędzie w stronę klienta.

3

Czwarte podejście polega na sposobie generowania i ustalonym wzorcu. Nie powinieneś mylić obsługi wyjątków (lub podnoszenia) z tym, w jaki sposób są wyświetlane lub rejestrowane, czy cokolwiek innego.

Jeśli masz wyjście (złapanego) wyjątku pod kontrolą, tzn. Możesz zmienić/zapisać odpowiedni kod, możesz po prostu użyć metody Exception.ToString(), która wyświetli zewnętrzny wyjątek, włącznie z wszystkimi "wewnętrznymi".

Uwaga: Uwaga: Wewnętrzne wyjątki nie są celowo wyświetlane przez aplikację. Na przykład w WCF (Windows Communication Foundation) wewnętrzny wyjątek nie jest nawet przenoszony z serwera na klienta, chyba że ustawiono IncludeExceptionDetails (przez config, kod, ...). Zwykle robi się to, ponieważ wewnętrzny wyjątek jest uważany za szczegół implementacji, który może dostarczyć osobie atakującej cenne informacje do złamania aplikacji.

0

Co z przesłonięciem właściwości StackTrace?

class CustomException : Exception { 

    public CustomException(string message, Exception inner) : base(message, inner) { 
    } 

    public override string StackTrace { 
     get { 
      if (InnerException != null) { 
       return InnerException.StackTrace; 
      } 
      return base.StackTrace; 
     } 
    } 
} 
+0

dzięki! Próbowałem ... Podczas wyświetlania żółtego ekranu śmierci, breakpoing po powrocie InnerException.Stacktrace został wywołany trzykrotnie i za każdym razem pokazywał oryginalny stacktrace. Ale dziwne jest to, że wciąż wyświetlał się nowy ślad stosu :( – helloworld

+0

@enableDeepak: nie wiedziałem, że to spowoduje, że wszechświat padnie na siebie ... przepraszam :( –

0

zgadzam, opcja 4 jest generalnie najlepiej ...

Jednakże w trakcie rozwoju, uważam, że to bardzo przydatne, aby umieścić całą klauzulę catch wewnątrz #if (DEBUG!), Ze wreszcie poza nim (w celu umożliwienia kompilacji w trybie debugowania):

#if (!DEBUG) 
catch (Exception ex) 
{ 
    // Catch logic for Release mode 
} 
#endif 
finally { } 

To sprawia, że ​​przerwę API w punkcie, w którym wystąpił błąd, zamiast na najwyższym poziomie.

Po prostu nie rób nawyku #if ...niemal we wszystkich innych przypadkach, należy

[Conditional("DEBUG")] 

przed metody zamiast

Powiązane problemy