2011-11-18 13 views
8

Possiedo un servizio WCF con più UI. Quando l'utente non è in grado di accedere al database, ottengo l'eccezione non autorizzata dal DB. Non rilevo l'eccezione sul lato server e la invio al client.Continuo a ricevere il servizio WCF in stato di errore sul lato client. Come devo rilevare le eccezioni WCF, senza interrompere il servizio WCF?

Sul client (pagina Web asp.net), visualizzo l'eccezione: l'utente non è riuscito ad accedere al database, l'accesso non è riuscito. Questo va tutto bene. Ma ... se faccio di nuovo una chiamata al servizio WCF, ottengo l'eccezione che il servizio è in stato di errore. L'apertura è solo per riavviare l'intero servizio WCF. Il servizio WCF è ospitato come servizio Windows.

Qual è il modo migliore per rilevare le eccezioni, registrare l'eccezione sul lato server, inviare i dettagli delle eccezioni al client senza interrompere il servizio? Grazie

+1

provare a utilizzare faultcontract. – Radhi

risposta

6

eccezioni non gestite potranno criticare la comunicazione canale. Come altri hanno sottolineato, un canale guasto deve essere interrotto chiamando lo Abort() - non può essere chiuso e non può essere riutilizzato.

Per indirizzare l'altra parte della domanda, "il modo migliore per rilevare le eccezioni, registrare l'eccezione sul lato server, inviare i dettagli delle eccezioni al client senza interrompere il servizio?", È necessario utilizzare FaultException Class.

Inoltre, è possibile utilizzare IErrorHandler Interface per collegare l'host di servizio per rilevare eventuali eccezioni non rilevate altrimenti (ad esempio un gestore di errori globale). Ci sono molti esempi su come farlo in rete - solo google per WCF IErrorHandler.

Ecco un paio:

WCF Exception Handling with IErrorHandler

WCF Extensibility – IErrorHandler

+0

grazie. quando devo rilevare le eccezioni e lanciare eccezioni di errore? nei contratti operativi o nel codice di avvio del servizio Windows che crea oggetti host del servizio? – InfoLearner

+0

È possibile rilevare l'eccezione nel servizio, serializzarlo come un contratto di errore e quindi il client (o il servizio Windows) può rilevare l'eccezione di errore in un blocco try-catch. – Tim

+0

Molto chiaro, grazie –

1

consultare il seguente link che parla di come i client WCF dovrebbero prendere i guasti/eccezioni e potenziali problemi che si possono incorrere in con il 'usando' dichiarazione in C#:

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

Baiscally è necessario chiama Abort() sul tuo client proxy. Questo imposterà immediatamente lo stato del proxy su Chiuso.

+0

oh fantastico. pensi che sia corretto restituire le eccezioni al client dal servizio wcf? – InfoLearner

+0

Penso che in realtà dipenda dal tipo di applicazione che stai creando e da quale sia la tua strategia generale di gestione delle eccezioni. Detto questo, se si tratta di un utente finale che si trova di fronte a un'applicazione, probabilmente vorrete far sapere loro che qualcosa è andato storto. –

2

È possibile utilizzare questo codice per creare una classe wrapper che gestire correttamente WCF eccezioni:

public class ServiceProxyHelper<TProxy, TChannel> : IDisposable 
    where TProxy : ClientBase<TChannel>, new() 
    where TChannel : class 
{ 
    /// 
    /// Private instance of the WCF service proxy. 
    /// 
    private TProxy _proxy; 

    /// 
    /// Gets the WCF service proxy wrapped by this instance. 
    /// 
    public TProxy Proxy 
    { 
     get 
     { 
      if (_proxy != null) 
      { 
       return _proxy; 
      } 
      else 
      { 
       throw new ObjectDisposedException("ServiceProxyHelper"); 
      } 
     } 
    } 

    public TChannel Channel { get; private set; } 

    /// 
    /// Constructs an instance. 
    /// 
    public ServiceProxyHelper() 
    { 
     _proxy = new TProxy(); 
    } 

    /// 
    /// Disposes of this instance. 
    /// 
    public void Dispose() 
    { 
     try 
     { 
      if (_proxy != null) 
      { 
       if (_proxy.State != CommunicationState.Faulted) 
       { 
        _proxy.Close(); 
       } 
       else 
       { 
        _proxy.Abort(); 
       } 
      } 
     } 
     catch (CommunicationException) 
     { 
      _proxy.Abort(); 
     } 
     catch (TimeoutException) 
     { 
      _proxy.Abort(); 
     } 
     catch (Exception) 
     { 
      _proxy.Abort(); 
      throw; 
     } 
     finally 
     { 
      _proxy = null; 
     } 
    } 
} 

È quindi possibile chiamare un servizio come questo:

using (ServiceProxyHelper<EmailServiceClient, EmailService> svc = 
    new ServiceProxyHelper<EmailServiceClient, EmailService>()) 
{ 
    svc.Proxy.SendMail(fromAddress, fromName, toEmail, toName, message); 
}