webentwicklung-frage-antwort-db.com.de

Das Kommunikationsobjekt System.ServiceModel.Channels.ServiceChannel kann nicht für die Kommunikation verwendet werden

Das Kommunikationsobjekt System.ServiceModel.Channels.ServiceChannel, kann nicht für die Kommunikation verwendet werden, da es sich im Fehlerzustand befindet. 

Worum geht es bei diesem Fehler und wie gehe ich vor, um ihn zu lösen?

132
Innova

Sie erhalten diesen Fehler, weil Sie eine .NET-Ausnahme auf Ihrer Serverseite auftreten lassen, die Sie nicht abgefangen und behandelt haben und auch nicht in einen SOAP -Fehler konvertiert haben.

Nun, da die serverseitige "Bombe" ausgebombt wurde, hat die WCF-Laufzeit den Kanal "fehlerhaft" gemacht - z. Die Kommunikationsverbindung zwischen dem Client und dem Server ist unbrauchbar - schließlich sieht es so aus, als ob Ihr Server gerade in die Luft gejagt wurde, sodass Sie nicht mehr mit ihm kommunizieren können.

Was Sie also tun müssen, ist:

  • immer fangen und behandeln Ihre serverseitigen Fehler - nicht Lassen Sie .NET-Ausnahmen vom Server an den Client weiterleiten - immer diese in interoperable SOAP fehler. Schauen Sie sich die WCF IErrorHandler - Schnittstelle an und implementieren Sie diese auf der Serverseite

  • wenn Sie gerade eine zweite Nachricht vom Client an Ihren Kanal senden, stellen Sie sicher, dass sich der Kanal nicht im fehlerhaften Zustand befindet:

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

    Wenn dies der Fall ist, können Sie es nur entsorgen, den clientseitigen Proxy erneut erstellen und es dann erneut versuchen

128
marc_s

Um zu verhindern, dass der Server in den Status Fault wechselt, müssen Sie sicherstellen, dass keine unbehandelte Ausnahme ausgelöst wird. Wenn WCF eine unerwartete Ausnahme sieht, werden keine Anrufe mehr angenommen - Sicherheit geht vor.
Zwei Möglichkeiten, dieses Verhalten zu vermeiden: 

  1. Verwenden Sie eine FaultException (diese ist für WCF nicht unerwartet, daher weiß die WCF, dass der Server noch einen gültigen Status hat.)
    anstatt 

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

    immer verwenden 

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

    vielleicht können Sie versuchen, den gesamten Block zu fangen und in allen Fällen einer Ausnahme eine FaultException auszulösen

    try   
    {  
        ... some code here   
    }
    catch (Exception ex)
    {  
        throw new FaultException(ex.Message)   
    }
    
  2. Weisen Sie WCF an, alle Ausnahmen mit einem Errorhandler zu behandeln. Dies kann auf verschiedene Arten erfolgen, ich habe eine einfache mit einem Attribut gewählt:
    Alles was wir noch tun müssen, ist das Attribut [SvcErrorHandlerBehaviour] für die gewünschte Service-Implementierung zu verwenden

    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);
            }
        }
    }
    

Dies ist ein einfaches Beispiel. Sie können tiefer in den IErrorhandler eintauchen, indem Sie nicht die unveränderte FaultException verwenden, sondern einen FaultException<> mit einem Typ, der zusätzliche Informationen enthält Ein detailliertes Beispiel finden Sie unter IErrorHandler .

26
BerndK

Fügen Sie das faulted-Ereignis hinzu, um herauszufinden, warum und wann der Fehler aufgetreten ist.

Edit: Es wäre auch hilfreich, wenn Sie weitere Informationen zu Ihren Aktivitäten posten würden.

7
flayn

In der Tat, wenn nach folgenden Vorschlägen von nicht erfolgreich marc_sBitte beachten Sie, dass ein <security> -Element in der Server-Bindungskonfiguration (oder dessen Fehlen) in web.config auf dem Server diese Ausnahme verursachen kann. Zum Beispiel erwartet der Server Message-Sicherheit und der Client ist auf None konfiguriert (oder, wenn der Server nicht Teil einer Active Directory-Domäne ist, der Remote-Client-Host jedoch).

Tipp: In solchen Fällen ruft die Client-App höchstwahrscheinlich die Web-Service-Geldstrafe auf, wenn sie direkt auf dem Server-Computer unter dem Administratorkonto in der RDP-Sitzung ausgeführt wird.

7
timmi4sa

Führen Sie den Dienst unter dem Visual Studio-Debugger aus, um dieses Problem zu diagnostizieren. Verwenden Sie das Menü: Debug | Exceptions und geben Sie an, dass Sie abbrechen möchten, wenn eine Exception ausgelöst wird. 

Die ursprüngliche Ausnahmebedingung hat eine viel bessere Fehlermeldung als "..es ist im Fehlerzustand." 

Ich habe zum Beispiel diese Ausnahme von ServiceHost.Open () erhalten, aber als ich die ursprüngliche Ausnahme zum Zeitpunkt der Auslösung feststellte, war die Fehlermeldung:

Dienst 'MyServiceName' hat keine Anwendung (keine Infrastruktur) Endpunkte. Möglicherweise wurde keine Konfigurationsdatei gefunden für Ihre Anwendung oder weil kein Serviceelement mit der .__ übereinstimmt. Der Servicename konnte in der Konfigurationsdatei gefunden werden oder weil nein Endpunkte wurden im Serviceelement definiert.

Durch das Beheben des Schreibfehler in App.config wurde das Problem behoben.

2
Dale Wilson

Ich habe einen Web-Client, der über WCF eine Verbindung zum Windows-Dienst herstellt. Meine Web-App gibt den gleichen Fehler aus

Das Kommunikationsobjekt System.ServiceModel.Channels.ServiceChannel kann nicht für die Kommunikation verwendet werden, da es sich im fehlerhaften Zustand befindet. Ich habe die WCF-Ablaufverfolgung aktiviert, was nicht viel geholfen hat .__Der Neustart des Windows-Dienstes hat es behoben und ich habe immer noch keine Idee von der Ursache. Die Fehlersuche sollte also immer von einfach aus beginnen. Dies ist ein Beispiel dafür. Wenn jemand ein ähnliches Problem hat, versuchen Sie, den Dienst neu zu starten.

2
yantaq

Ich hatte ein anderes Problem, von dem ich glaube, dass es in den anderen Antworten nicht erwähnt wurde.

Ich muss Endpunkte auf derselben TCP-Adresse und demselben Port bedienen. In der app.config hatte ich vergessen, beide Endpunkte hinzuzufügen, sodass der Dienst auf dem richtigen Port ausgeführt wurde, jedoch mit der falschen Dienstschnittstelle.

1
Karsten

Ich hatte das gleiche Problem beim Versuch, net.tcp-wcf-Serviceendpunkt in einem http-asmx-Service zu verbrauchen. 

Wie ich gesehen habe, hat niemand eine spezifische Antwort geschrieben. WARUM tritt dieses Problem auf, aber nur, wie man richtig damit umgeht.

Ich habe mehrere Tage hintereinander damit zu kämpfen gehabt und endlich herausgefunden, woher das Problem in meinem Fall kommt.

Anfangs dachte ich, wenn Sie einen Verweis auf einen Dienst machen, wird die Konfigurationsdatei in Bezug auf das Sicherheitsetikett auf dieselbe Weise wie in der Quelle konfiguriert. Dies war jedoch nicht der Fall, und ich sollte mich manuell darum kümmern Fall hatte ich nur

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

Später habe ich gesehen, dass der Sicherheitsteil fehlt und so aussehen sollte

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

Das zweite Problem in meinem Fall war, dass ich transferMode="Streamed" für meinen Quell-WCF-Dienst verwendet habe und im Client hatte ich nichts Bestimmtes, was schlecht war, da die Standardvariable transferModeBuffered ist und es wichtig ist, dass sowohl Quelle als auch Client konfiguriert werden auf die gleiche Weise.

1
ppenchev

Wenn diese Meldung in Debug aus Visual Studio angezeigt wird und die Lösung das WCF-Projekt enthält ..__ Öffnen Sie dann diese WCF-Projekteinstellungen -> gehen Sie auf die Registerkarte "WCF-Optionen" -> Aus "WCF-Service-Host beim Debuggen starten ..."

1
Horev Ivan

Für mich war es ein Problem mit Load Balancer/URL. Ein Web-Service hinter einem Load Balancer hat einen anderen Service hinter demselben Load Balancer mit der vollständigen URL wie folgt aufgerufen: loadbalancer.mycompany.com. Ich habe es so geändert, dass der Load Balancer umgangen wird, wenn der zweite Service aufgerufen wird, indem stattdessen localhost.mycompany.com verwendet wird.

Ich denke, es gab eine Art Zirkelverweisproblem mit dem Load Balancer.

0
goku_da_master

In meinem Fall war der Grund ein falsches Zertifikat, das nicht geladen werden konnte. Ich fand es in der Ereignisanzeige unter System heraus:

Beim Versuch, auf den TLS-Server zuzugreifen, ist ein schwerwiegender Fehler aufgetreten Privater Schlüssel des Berechtigungsnachweises. Der von der kryptografischen .__ zurückgegebene Fehlercode. Modul ist 0x8009030D. Der interne Fehlerzustand ist 10001.

0
altumano

Dieser Fehler kann auch von Ihrem eigenen Computer ausgelöst werden und nicht nur eine unbehandelte Ausnahme. Wenn die Uhrzeit Ihres Servers/Computers um zu viele Minuten abgelaufen ist, lehnen viele .NET-Webdienste Ihre Anforderung mit einem nicht behandelten Fehler ab. Es wird aus ihrer Sicht behandelt, aber aus Ihrer Sicht nicht behandelt. Stellen Sie sicher, dass die Uhrzeit Ihres Empfängerservers korrekt ist. Wenn das Problem behoben werden muss, müssen Sie den Dienst zurücksetzen oder neu starten, bevor der Kanal erneut geöffnet wird.

Dieses Problem ist auf einem Server aufgetreten, auf dem die Firewall die Internetzeitaktualisierung blockierte und der Server aus irgendeinem Grund die Zeit abbrach. Alle .NET-Webdienste von Drittanbietern sind fehlerhaft, weil sie alle Webdienstanfragen abgelehnt haben. Durch das Eingraben in die Ereignisanzeige konnte das Problem identifiziert werden. Durch das Anpassen der Uhr wurde das Problem behoben. Der Fehler war auf unserer Seite, obwohl wir die Fehlermeldung über einen fehlerhaften Status für zukünftige Webdienstaufrufe erhalten haben.

0
HBlackorby

Ich weiß, dass dies ein älterer Beitrag ist, aber wenn Sie die Sicherheit nicht ändern können, sollten Sie unbedingt sicherstellen, dass Ihr Benutzername und Ihr Kennwort festgelegt sind.

Ich hatte einen Dienst mit authenticationMode als UserNameOverTransport. Wenn der Benutzername und das Kennwort nicht für den Dienstclient festgelegt wurden, würde ich diesen Fehler erhalten.

0
Joshua G

Der Server bricht automatisch Verbindungen ab, über die keine Nachricht empfangen wurde, und zwar für die Dauer, die dem Empfangszeitlimit entspricht ( Standard ist 10 Minuten ). Dies ist eine DoS-Einschränkung, um zu verhindern, dass Clients den Server zwingen, Verbindungen auf unbestimmte Zeit zu öffnen.

Da der Server die Verbindung abbricht, weil die Verbindung unterbrochen wurde, erhält der Client diese Ausnahme. 

Sie können steuern, wie lange der Server zulässt, dass eine Verbindung inaktiv ist, bevor Sie sie abbrechen, indem Sie das Empfangszeitlimit für die Bindung des Servers konfigurieren Credit: T.R.Vishwanath - MSFT

0
Vijay Rana