2009-08-13 22 views
7

Mam standardową przekazanie błędzie w miejscu w mojej służbie:Jak radzić sobie z błędami WCF o niskim poziomie?

  • Mam IErrorHandler podpięty do służby do obsługi nieoczekiwanych błędów podczas wykonywania usługi.
  • Mam try/catch bloków we wszystkich moich metod obsługi do obsługi oczekiwanych przypadków.

Istnieją jednak przypadki, w których wyjątki są zgłaszane na serwerze i nie są wywoływane.

Oto przypadek, gdy wyjątek serwer nie jest wysyłany do IErrorHandler:

  • Ustaw receiveTimout na wiązania do 5 sekund na serwerze.

  • Na kliencie to zrobić:

.

Service1Client sc = new Service1Client(); 
ICommunicationObject o = sc as ICommunicationObject; 

o.Open(); // open channel 

sc.GetData(10); // do a first call 

Thread.Sleep(10000); // wait longer than the server receiveTimeout 

sc.GetData(10); // Attempt another call: server throws a FaulException 

W takim przypadku błąd jest zgłaszany na serwerze, ale nie mogę znaleźć sposobu na jego obsługę (i zaloguj się). Wiem, że błąd jest zgłaszany, ponieważ jeśli dołączę debuggera do procesu serwera i złamie wszystkie wyjątki, debugger się zepsuje.

Znalazłem inne podobne przypadki, w których błędy niskiego poziomu nie zostały przekazane do mojego programu.

Gdzie mogę podłączyć mój kod, aby upewnić się, że mogę obsłużyć WSZYSTKIE wyjątki, które występują na serwerze, zanim zostaną one zwrócone do aplikacji klienckiej? Czy powinienem wdrożyć własny IChannel lub inny interfejs niskiego poziomu?

Dzięki

UPDATE 21 września 2009: Zobacz this wątek na Forum Microsoft WCF. Prawdopodobnie będę musiał zaimplementować własny kanał, jeśli chcę obsłużyć ten typ wyjątku. Zaktualizuję ten wpis, gdy będę mieć więcej informacji.

+0

Powiązanie serwera receiveTimeout nie powinno być tutaj aktywne - wystarczyłoby, gdyby otrzymanie odpowiedzi z wywołania GetData() zajęło więcej niż 5 sekund. Twój klient śpiący przez 10 sekund nie działa. Założenie początkowej usługi testowej i aktualizacja powiązania serwera z ustawieniem receiveTimeout na 5 sekund nie powoduje odtworzenia problemu. Jaka jest usterka w odbiorze u klienta? Podejrzewam niepoprawnie skonfigurowane wiązanie/zachowanie serwera, szczególnie jeśli nie włamujesz się do usługi w twoim kodzie. Włącz debugowanie WCF na kliencie/usłudze i zobacz, co pokazuje. –

+0

Zgodnie z opisem w MSDN, serwer receiveTimeout to maksymalny czas oczekiwania serwera na bezczynny otwarty kanał. W takim przypadku ilość czasu jest większa. Wyjątkiem na kliencie jest wyjątek MessageSecurityException, który ma wewnętrzny wyjątek FautException. Wewnętrzny wyjątek FaultException stwierdza przekroczenie wartości receiveTimeout. – Sylvain

+0

Interesujące. Sądzę, że to może być wskazówka, dlaczego zadziałało na pierwsze połączenie, a nie na drugie. Czy możesz przesłać link do dokumentacji, do której odsyłasz na receiveTimeout? Obawiam się, że moje zrozumienie tej wartości jest błędne. Dokumenty, do których się odwołuję, to http://msdn.microsoft.com/en-us/library/ms731299.aspx, dziękuję! –

Odpowiedz

5

Po wielu badań i eksperymentów, odpowiedź brzmi:

W tym momencie (.NET 3.5) nie ma mechanizmu, który pozwala obsłużyć wszystkie możliwe wyjątki, które mogą wystąpić w kontekście wywołania WCF.

wyjątkami, które zdarzają się podczas wykonywania metody usługi można łatwo obchodzić się z:

  1. bloków try/catch we wszystkich metod usługi do obsługi spodziewanych przypadków.
  2. IErrorHandler podłączony do usług w celu obsługi nieoczekiwanych błędów podczas wykonywania usługi.

Jednak w przypadku błędów infrastruktury WCF o niskim poziomie nie ma idealnego rozwiązania. Najlepszym rozwiązaniem wydaje się być zaimplementowanie niestandardowego kanału w celu wychwycenia większej liczby wyjątków.

W this Microsoft Connect Bug Report firma Microsoft potwierdza, że ​​nie ma sposobu na obsłużenie wszystkich typów błędów infrastruktury WCF.

W dokumencie this thread on the Microsoft WCF forums znajduje się przykład dotyczący implementacji kanału niestandardowego. To rozwiązanie działa tylko dla HTTP, a nie dla HTTPS. Również niektóre błędy infrastruktury WCF nie są przechwytywane przez niestandardowy kanał (więcej szczegółów w tym wątku).

+0

@Anonymous down-voter: Naprawdę chciałbym wiedzieć, dlaczego głosowanie w dół. To jest poprawna odpowiedź. Jeśli znasz lepszą odpowiedź, opublikuj ją. – Sylvain

0

Chodzi o to, że jeśli serwer nie jest osiągalny lub nie może obsłużyć wiadomości, nie wystąpi błąd na serwerze - błąd pojawi się na kliencie ("TimeoutException" lub inne).

Tak więc w tych przypadkach fakt, że IErrorHandler na serwerze naprawdę nie pomoże - ponieważ błąd rzeczywiście dzieje się na kliencie (nie można nawiązać połączenia, z powodu braku połączenia z siecią lub literówki w adresie serwera lub sstuffie, np. że).

Tak więc po stronie klienta zdecydowanie musisz także użyć polecenia try ... catch wokół wszystkich połączeń z serwerem.

Marc

+2

Nieprawidłowe. To serwer odmawia obsługi połączenia, ponieważ termin receiveTimeout wygasł. Dlatego wyjątek jest zgłaszany przez serwer. Jak napisałem, mogę dołączyć debuggera do procesu serwera, a następnie widzę, że wyjątek jest podnoszony; Problem polega na tym, że nie jest przekazywany do programu obsługi, zanim zostanie zwrócony klientowi. Potrzebuję sposobu na obsłużenie tego wyjątku na serwerze. – Sylvain

+0

OK, masz rację dla receiveTImeout - ale inne błędy (szczególnie błędy komunikacji) mogą się zdarzyć, gdy klient próbuje się połączyć i nigdy nie dojdzie do serwera, aw tych przypadkach IErrorHandler na serwerze oczywiście naprawdę nie ma sensu. –

+0

Zgadza się; w niektórych przypadkach (na przykład serwer nie działa) błąd wystąpi tylko na kliencie. Ale w tych przypadkach, w których występuje na serwerze, muszę się upewnić, że obsługuję je wszystkie. – Sylvain

0

Skonfiguruj śledzenie diagnostyczną i sprawdzić logi z Service Trace Viewer Tool. Łącze zawiera również informacje o konfiguracji śledzenia.

+1

Zrobiłem; Widzę błąd na serwerze w śledzeniu. Nie chcę "śledzić" tych przypadków, chcę je "obsłużyć". – Sylvain

+0

Śledzenie pomoże zrozumieć, gdzie i dlaczego występują wyjątki, co miał na myśli (śledzenie zarówno klienta, jak i usługi). Prawidłowe postępowanie z wyjątkami na poziomie operacji (try/catch/throw faultexception) i IErrorHandler powinny obejmować twoje bazy (przynajmniej myślałem). Tam, gdzie może to spaść, jest błąd w implementacji IErrorHandler lub problem z konfiguracją usługi, dzięki czemu obsługa wyjątków ma błąd i nie jest dokładnie zgłaszana. Zdecydowanie ciekawy, czy to nie dotyczy wszystkich baz! –

+0

Jak można "obsłużyć" ten wyjątek? –

2

Użyj umów typu FaultContracts. Następnie błąd można obsłużyć po stronie klienta.

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

http://www.c-sharpcorner.com/UploadFile/ankithakur/ExceptionHandlingWCF12282007072617AM/ExceptionHandlingWCF.aspx

Jest to również znacznie lepiej do debugowania, ponieważ często będzie opracowanie klienta i nie chcesz, aby obniżyć serwer dla celów debugowania.

Na kliencie należy użyć bloków try/catch, aby przechwycić wszystkie wyjątki/błędy. Zdecydowanie są błędy, które nie mogą zostać wykryte na końcu serwera, takie jak problem z komunikacją, więc i tak musisz obsługiwać błędy po stronie klienta.

Jeśli chcesz scentralizować obsługę błędów, możesz utworzyć usługę, która odbierze wiadomości o wszystkich błędach, wyśle ​​błąd do tego serwera i zapisze go. Może to być przydatne, jeśli chcesz utworzyć scentralizowany wiadomość śledzenia/Przedstawienie analizy/narzędzie rejestrowania i mają dużą liczbę procesorów aplikacyjnych, serwerów, klientów itp

+1

Używam również FaultContracts. Ale w tym konkretnym przypadku błąd ma miejsce przed wykonaniem operacji. Tak więc nie mam nawet szansy na konwersję wyjątku na wyjątek FaultException . – Sylvain

Powiązane problemy