L'oggetto di comunicazione, System.ServiceModel.Channels.ServiceChannel, non può essere utilizzato per la comunicazione


156

L'oggetto di comunicazione, System.ServiceModel.Channels.ServiceChannel, non può essere utilizzato per la comunicazione perché si trova nello stato Faulted.

Di cosa tratta questo errore e come potrei fare per risolverlo?

Risposte:


151

Questo errore viene visualizzato perché si è verificata un'eccezione .NET sul lato server e non è stata rilevata e gestita e nemmeno convertita in un errore SOAP.

Ora da quando il lato server è "bombardato", il runtime WCF ha "danneggiato" il canale - ad esempio, il collegamento di comunicazione tra il client e il server è inutilizzabile - dopo tutto, sembra che il tuo server sia esploso, quindi non puoi comunicare con ancora.

Quindi quello che devi fare è:

  • intercettare e gestire sempre gli errori sul lato server - non lasciare che le eccezioni .NET viaggino dal server al client - avvolgerli sempre in errori SOAP interoperabili. Controlla l' interfaccia IErrorHandler di WCF e implementala sul lato server

  • se stai per inviare un secondo messaggio sul tuo canale dal client, assicurati che il canale non sia nello stato difettoso:

    if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
    {
       // call service - everything's fine
    }
    else
    {
       // channel faulted - re-create your client and then try again
    }

    In tal caso, è sufficiente eliminarlo e ricreare nuovamente il proxy lato client, quindi riprovare


11
Sembra che lo stesso errore possa verificarsi anche quando il problema è sul lato client: ad esempio, quando è stata superata la quota della dimensione del messaggio per i messaggi in arrivo.
svick,

6
Come posso ricreare il client?
Masoud,

32

Per evitare che il server cada nello stato di errore, è necessario assicurarsi che non venga sollevata alcuna eccezione non gestita. Se WCF rileva un'eccezione imprevista, non vengono più accettate chiamate, innanzitutto la sicurezza.
Due possibilità per evitare questo comportamento:

  1. Utilizzare una FaultException (questa non è inaspettata per WCF, quindi WCF sa che il server ha ancora uno stato valido)
    invece di

    throw new Exception("Error xy in my function")  

    usare sempre

    throw new FaultException("Error xy in my function")  

    forse puoi provare..catch l'intero blocco e lanciare una FaultException in tutti i casi di un'eccezione

    try   
    {  
        ... some code here   
    }
    catch (Exception ex)
    {  
        throw new FaultException(ex.Message)   
    }
  2. Di 'a WCF di gestire tutte le eccezioni usando un gestore di errori. Questo può essere fatto in diversi modi, ne ho scelto uno semplice usando un attributo:
    tutto ciò che dobbiamo fare di più è usare l'attributo [SvcErrorHandlerBehaviour]sull'implementazione del servizio desiderata

    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    
    namespace MainService.Services
    {
        /// <summary>
        /// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
        /// </summary>
        public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
        {
            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            { } //implementation not needed
    
            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
                                             BindingParameterCollection bindingParameters)
            { } //implementation not needed
    
            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
                foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
                {
                    ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
                    if (channelDispatcher == null)
                        continue;
                    channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
                }
            }
        }
    
        public class SvcErrorHandler: IErrorHandler
        {
            public bool HandleError(Exception error)
            {
                //You can log th message if you want.
                return true;
            }
    
            public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
            {
                if (error is FaultException)
                    return;
    
                FaultException faultException = new FaultException(error.Message);
                MessageFault messageFault = faultException.CreateMessageFault();
                msg = Message.CreateMessage(version, messageFault, faultException.Action);
            }
        }
    }

Questo è un semplice esempio, puoi approfondire IErrorhandler non usando il nudo FaultException, ma FaultException<>con un tipo che fornisce informazioni aggiuntive vedi IErrorHandler per un esempio dettagliato.


10

È un dato di fatto, se non riesce dopo aver seguito i suggerimenti di marc_s , tenere presente che un elemento <security> nella configurazione dell'associazione server (o la sua mancanza) in web.config sul server può causare questa eccezione. Ad esempio, il server si aspetta una Messagesicurezza di livello e il client è configurato su None(o, se il server non fa parte di un dominio Active Directory ma l'host del client remoto lo è).

Suggerimento: in questi casi l'app client molto probabilmente invocherà il servizio Web correttamente se eseguita direttamente sul computer server con account amministrativo nella sessione RDP.


2

Per diagnosticare questo problema, eseguire il servizio nel debugger di Visual Studio. Utilizzare il menu: Debug | Eccezioni e indicare che si desidera interrompere quando viene generata un'eccezione.

L'eccezione originale generata avrà un messaggio di errore molto migliore di "..è nello stato Faulted".

Ad esempio, stavo ottenendo questa eccezione da ServiceHost.Open (), ma quando ho rilevato l'eccezione originale al momento del lancio, il messaggio di errore era:

Il servizio "MyServiceName" ha endpoint di applicazione zero (non infrastrutturali). Ciò può essere dovuto al fatto che non è stato trovato alcun file di configurazione per la propria applicazione o che non è stato trovato alcun elemento di servizio corrispondente al nome del servizio nel file di configurazione o che non sono stati definiti endpoint nell'elemento di servizio.

La correzione dell'errore di ortografia in App.config ha risolto il problema.


In VS2015 selezionare Debug → Impostazioni eccezioni e selezionare Eccezioni Common Language Runtime.
SharpC

1
Quindi perché l'eccezione originale non è stata data fino a quando non hai utilizzato il debugger di Visual Studio?
Jez

2

Ho avuto lo stesso problema durante il tentativo di consumare endpoint del servizio wcf net.tcp in un servizio http asmx.

Come ho visto nessuno ha scritto una risposta specifica PERCHÉ si verifica questo problema, ma solo come gestirlo correttamente.

Ho lottato con esso per diversi giorni di seguito e alla fine ho scoperto da dove proviene il problema nel mio caso.

Inizialmente ho pensato che quando si fa riferimento a un servizio, il file di configurazione verrà configurato per quanto riguarda il tag di sicurezza nello stesso modo in cui si trova nella fonte, ma non era così e dovrei occuparmene manualmente. Nel mio caso avevo solo

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService"
    </binding>
</netTcpBinding>`

Più tardi ho visto che manca la parte di sicurezza e dovrebbe apparire così

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
      <security mode="None">
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </netTcpBinding>

Il secondo problema nel mio caso era che stavo usando transferMode="Streamed"sul mio servizio WCF di origine e nel client non avevo nulla di specifico al riguardo, il che era male, perché il valore predefinito transferModeè Buffereded è importante in entrambi i luoghi sorgente e client essere configurati nello stesso modo.


1

Ho avuto un altro problema, che non credo sia stato menzionato nelle altre risposte.

Devo servire gli endpoint sullo stesso indirizzo e porta tcp. In app.config, avevo dimenticato di aggiungere entrambi gli endpoint, quindi il servizio era in esecuzione sulla porta corretta, ma con l'interfaccia di servizio errata.


1

Se vedi questo messaggio in Debug da Visual Studio e la soluzione contiene un progetto WCF. Quindi apri le impostazioni di questo progetto WCF -> vai alla scheda "Opzioni WCF" -> off "Avvia l'host del servizio WCF durante il debug ..."


Ho avuto lo stesso problema e mi sono bloccato su questo problema per un bel po '. Probabilmente non è una buona pratica avere client e server sulla stessa soluzione. Grazie!
yoosha,

1

Per me il problema è stato causato dal file di configurazione generato automaticamente importando il WSDL. Ho aggiornato l'associazione da basicHttpBinding a customBinding. L'aggiunta di un'ulteriore gestione delle eccezioni non ha aiutato a precisarlo.

Prima

<basicHttpBinding>
            <binding name="ServiceName">
                <security mode="Transport" />
            </binding>
        </basicHttpBinding>`

Dopo

<customBinding>
        <binding name="ServiceName">
          <textMessageEncoding messageVersion="Soap12" />
          <httpsTransport />
        </binding>
      </customBinding>`

0

Nel mio caso il motivo era un certificato errato che non poteva essere caricato. L'ho scoperto dal Visualizzatore eventi, sotto Sistema:

Si è verificato un errore irreversibile durante il tentativo di accedere alla chiave privata delle credenziali del server TLS. Il codice di errore restituito dal modulo crittografico è 0x8009030D. Lo stato di errore interno è 10001.


0

Questo errore può essere attivato anche dal tuo computer e non solo un'eccezione non gestita. Se il tuo server / computer ha il tempo di inattività di troppi minuti, molti servizi web .NET rifiuteranno la tua richiesta con un errore non gestito. È gestito dal loro punto di vista, ma non gestito dal tuo punto di vista. Verificare che l'ora del server ricevente sia corretta. Se deve essere riparato, dovrai ripristinare il servizio o riavviare prima che il canale si riapra.

Ho riscontrato questo problema su un server in cui il firewall ha bloccato l'aggiornamento dell'ora di Internet e il server si è spento per qualche motivo. Tutti i servizi Web .NET di terze parti sono andati in errore perché hanno rifiutato qualsiasi richiesta di servizio Web. Scavare nel Visualizzatore eventi ha contribuito a identificare il problema, ma la regolazione dell'orologio ha risolto il problema. L'errore è stato da parte nostra anche se abbiamo ricevuto il messaggio di errore Stato di errore per future chiamate al servizio Web.


0

Il server interromperà automaticamente le connessioni per le quali non è stato ricevuto alcun messaggio per la durata pari al timeout di ricezione (il valore predefinito è 10 minuti ). Questa è una mitigazione DoS per impedire ai client di forzare il server ad avere connessioni aperte per un periodo di tempo indefinito.

Poiché il server interrompe la connessione perché è inattiva, il client ottiene questa eccezione.

È possibile controllare per quanto tempo il server consente a una connessione di rimanere inattiva prima di interromperla configurando il timeout di ricezione sull'associazione del server. Credito: TRVishwanath - MSFT


0

So che questo è un post più vecchio, ma una cosa a cui prestare attenzione quando non è possibile modificare la sicurezza è assicurarsi che il nome utente e la password siano impostati.

Ho avuto un servizio con autenticazioneMode come UserNameOverTransport, quando il nome utente e la password non sono stati impostati per il client di servizio otterrei questo errore.


0

Per me è stato un problema di bilanciamento del carico / url. Un servizio web dietro un bilanciatore di carico chiamato un altro servizio dietro lo stesso bilanciamento del carico utilizzando l'URL completo, come: loadbalancer.mycompany.com. L'ho modificato per bypassare il bilanciamento del carico quando si chiama il secondo servizio utilizzando localhost.mycompany.cominvece.

Penso che ci fosse una sorta di problema di riferimento circolare in corso con il bilanciamento del carico.


-2

Non è una soluzione a questo problema, ma se si verifica l'errore sopra riportato con Ektron eSync, è possibile che il database abbia esaurito lo spazio su disco.

Modifica: In realtà questo non è interamente un problema di Ektron eSync. Questo può accadere su qualsiasi servizio che richiede un database completo.

Modifica: lo spazio su disco insufficiente o il blocco dell'accesso a una directory necessaria causeranno questo problema.


Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post: puoi sempre commentare i tuoi post e una volta che avrai una reputazione sufficiente sarai in grado di commentare qualsiasi post .
Dariusz,

2
Ho risposto alla sua domanda "come potrei fare per risolverlo?", Non è colpa mia se non ci ha mai fornito i dettagli sul fatto che stesse usando Ektron o meno. Ho anche bisogno di 50 rappresentanti per commentare il suo post.
Jonathan Bick,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.