2009-08-13 20 views
7

ho la consegna standard error in atto nel mio servizio:Come gestire gli errori WCF di basso livello?

  • Ho un IErrorHandler agganciato al servizio per gestire gli errori imprevisti durante l'esecuzione del servizio.
  • Ho provato/catturare blocchi in tutti i miei metodi di servizio per gestire i casi previsti.

Tuttavia, ci sono casi in cui vengono lanciate eccezioni sul server e nessuno dei due viene chiamato.

Ecco un caso in cui l'eccezione server non viene inviato al IErrorHandler:

  • Impostare la receiveTimout sul server vincolante per 5 secondi.

  • Sul client fare questo:

.

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 

In questo caso, l'errore viene generato sul server ma non riesco a trovare un modo per gestire la cosa (e di accedervi). So che un errore viene generato perché se allego un debugger sul processo del server e interrompo su tutte le eccezioni, il debugger si interrompe.

Ho trovato altri casi simili in cui gli errori di basso livello non vengono passati al mio programma.

Dove posso agganciare il mio codice per garantire che possa gestire TUTTE le eccezioni che si verificano sul server prima che vengano restituite all'app client? Devo implementare il mio proprio IChannel o qualche altra interfaccia di basso livello?

Grazie

UPDATE 21 Settembre 2009: Vedere this filo sul Microsoft WCF Forum. Probabilmente dovrò implementare il mio canale se voglio gestire questo tipo di eccezione. Aggiornerò di nuovo questo post quando avrò più informazioni.

+0

Il binding del server receiveTimeout non dovrebbe essere in riproduzione qui - solo se ci vuole più di 5 secondi per ricevere risposta dalla chiamata a GetData(). Il tuo cliente che dorme per 10 secondi non ha alcun effetto. Supponendo che il servizio di test iniziale e l'aggiornamento del binding del server per impostare receiveTimeout su 5 secondi non riproducono il problema. Qual è l'errore che si riceve sul client? In realtà sospetto un binding/comportamento del server configurato in modo errato, specialmente se non si interrompe il servizio nel codice. Abilita il debug di WCF su client/servizio e guarda cosa mostra. –

+0

Come descritto in MSDN, il server receiveTimeout è il tempo massimo che il server attenderà per un canale inattivo aperto. In tal caso la quantità di tempo è superiore. L'eccezione sul client è una MessageSecurityException che ha una FautException interna. La FaultException interna indica che il receiveTimeout ha superato. – Sylvain

+0

Interessante. Immagino che potrebbe anche essere un indizio sul perché ha funzionato sulla prima chiamata e non sulla seconda. Puoi inoltrare un link alla documentazione a cui ti riferisci su receiveTimeout? Ho paura che la mia comprensione di questo valore sia difettosa. I documenti a cui faccio riferimento sono http://msdn.microsoft.com/en-us/library/ms731299.Aspx, grazie! –

risposta

5

Dopo molte ricerche e sperimentazioni, la risposta è:

In questo momento (.Net 3.5) non esiste alcun meccanismo che consenta di gestire tutte le possibili eccezioni che possono verificarsi nel contesto di una chiamata WCF.

eccezioni che si verificano durante l'esecuzione metodo di servizio possono essere facilmente gestiti con:

  1. blocchi try/catch in tutti i metodi di servizio per gestire casi attesi.
  2. IErrorHandler collegato ai servizi per gestire errori imprevisti durante l'esecuzione del servizio.

Tuttavia, per errori di infrastruttura WCF di basso livello, non esiste una soluzione perfetta. La migliore soluzione esistente sembra essere quella di implementare un canale personalizzato per catturare più eccezioni.

In this Microsoft Connect Bug Report, Microsoft conferma che non è possibile gestire tutti i tipi di errori dell'infrastruttura WCF.

In this thread on the Microsoft WCF forums, c'è un esempio su come implementare un canale personalizzato. Quella soluzione funziona solo per HTTP, non per HTTPS. Anche alcuni errori dell'infrastruttura WCF non vengono catturati dal canale personalizzato (vedi più dettagli in quel thread specifico).

+0

@Anonimo down-voter: mi piacerebbe davvero sapere perché il down vote. Questa è la risposta corretta. Se si conosce una risposta migliore, si prega di postarlo. – Sylvain

0

Il punto è: se il server non è raggiungibile o non è in grado di gestire il messaggio, non si verificherà alcun errore sul server: l'errore verrà visualizzato sul client ("TimeoutException" o altri).

Quindi, in questi casi, avendo l'IErrorHandler sul server non è realmente di aiuto andando - poiché l'errore realmente accade sul client (nessun collegamento può essere fatto, a causa di rete verso il basso, o errore di battitura nel indirizzo del server o sstuff come quella).

Quindi, sul lato client, è anche necessario utilizzare try .... prendere tutte le chiamate del server.

Marc

+2

Non corretto. È il server che si rifiuta di gestire la chiamata perché il receiveTimeout è scaduto. Pertanto l'eccezione viene sollevata dal server. Come ho scritto, posso attaccare il debugger sul processo del server e poi vedo l'eccezione sollevata; il problema è che non viene passato a un gestore prima di essere restituito al client. Ho bisogno di un modo per gestire questa eccezione sul server. – Sylvain

+0

OK, hai ragione per receiveTImeout - ma altri errori (in particolare errori di comunicazione) potrebbero accadere mentre il client sta tentando di connettersi e non arriveranno mai al server, e in questi casi, IErrorHandler sul server ovviamente è inutile, davvero. –

+0

Proprio così; in alcuni casi (il server è inattivo ad esempio), l'errore si verifica solo sul client. Ma per quei casi in cui si verifica sul server, devo assicurarmi che li gestisca tutti. – Sylvain

0

Configurare l'analisi diagnostica e controllare i registri con Service Trace Viewer Tool. Il link contiene anche informazioni sulla configurazione della traccia.

+1

Ho fatto; Vedo l'errore sul server nella traccia. Non voglio "tracciare" questi casi, voglio "gestirli". – Sylvain

+0

La traccia aiuterà a capire dove e perché si verificano le eccezioni è ciò che penso che intendesse (traccia sia il client che il servizio). Gestendo correttamente le eccezioni a livello di operazione (try/catch/throw faultexception) e un IErrorHandler dovrebbe coprire le basi (almeno pensavo). Dove ciò potrebbe cadere è un bug nell'implementazione di IErrorHandler o un problema con la configurazione del servizio in modo che la stessa gestione delle eccezioni abbia un errore e non riporti accuratamente il problema. Sicuramente interessato a sapere se questo non copre tutte le basi! –

+0

Come si "gestirà" questa eccezione? –

2

Utilizzare FaultContracts. Quindi l'errore può essere gestito dal cliente.

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

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

Questo è anche molto meglio per il debug, dal momento che spesso si svilupperà un client e non vogliono far cadere il server per il debug.

Sul lato client, utilizzare i blocchi try/catch per catturare tutte le eccezioni/guasti. Ci sono sicuramente errori che non possono essere rilevati sul server, come ad esempio un problema di comunicazione, quindi è comunque necessario gestire gli errori sul client.

Se si desidera la gestione centralizzata degli errori, è possibile creare un servizio che accetta i messaggi relativi a tutti gli errori, invia l'errore a quel server e lo registra. Questo può essere utile se si vuole creare un messaggio centralizzato tracing/strumento di analisi/registrazione delle prestazioni e hanno un gran numero di applicazioni processori, server, client ecc

+1

Uso anche FaultContracts. Ma in questo caso specifico, l'errore si verifica molto prima dell'esecuzione dell'operazione. Quindi non ho nemmeno la possibilità di convertire l'eccezione in FaultException . – Sylvain

Problemi correlati