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

156

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

Worum geht es bei diesem Fehler und wie würde ich ihn lösen?

Innova
quelle

Antworten:

151

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

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

Was Sie also tun müssen, ist:

  • immer fangen und Ihre serverseitige Fehler behandeln - nicht .NET Ausnahmen vom Server an den Client reisen lassen - immer diejenigen in interoperable SOAP - Fehler wickeln. Überprüfen Sie die WCF IErrorHandler- Schnittstelle und implementieren Sie sie auf der Serverseite

  • Wenn Sie vom Client eine zweite Nachricht an Ihren Kanal senden möchten, 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 und den clientseitigen Proxy erneut erstellen und dann erneut versuchen

marc_s
quelle
11
Es scheint, dass der gleiche Fehler auftreten kann, wenn das Problem auch auf der Clientseite liegt: Zum Beispiel, wenn das Kontingent für die Nachrichtengröße für eingehende Nachrichten überschritten wurde.
Svick
6
Wie kann ich den Client neu erstellen?
Masoud
32

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

  1. Verwenden Sie einen FaultException (dies nicht unerwartet für WCF ist, so dass der WCF weiß , dass der Server noch einen gültigen Zustand hat)
    statt

    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 abzufangen 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 Fehlerbehandler zu behandeln. Dies kann auf verschiedene Arten geschehen. Ich habe ein einfaches mit einem Attribut ausgewählt:
    Alles, was wir 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 den nackten verwenden FaultException, sondern einen FaultException<>mit einem Typ, der zusätzliche Informationen bietet. Ein detailliertes Beispiel finden Sie unter IErrorHandler .

BerndK
quelle
10

Wenn dies nach Befolgung der Vorschläge von marc_s nicht erfolgreich ist, beachten Sie bitte, dass ein <security> -Element in der Serverbindungskonfiguration (oder ein Mangel daran) in web.config auf dem Server diese Ausnahme verursachen kann. Beispielsweise erwartet der Server MessageSicherheit auf Level-Ebene und der Client ist dafür konfiguriert None(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 den Webdienst auf, wenn sie direkt auf dem Server unter dem Administratorkonto in der RDP-Sitzung ausgeführt wird.

timmi4sa
quelle
2

Führen Sie den Dienst unter dem Visual Studio-Debugger aus, um dieses Problem zu diagnostizieren. Verwenden Sie das Menü: Debug | Ausnahmen und geben Sie an, dass Sie beim Auslösen einer Ausnahme abbrechen möchten.

Die ursprünglich ausgelöste Ausnahme hat eine viel bessere Fehlermeldung als "..es ist im fehlerhaften Zustand."

Zum Beispiel habe ich diese Ausnahme von ServiceHost.Open () erhalten, aber als ich die ursprüngliche Ausnahme zum Zeitpunkt des Auslösens abfing, lautete die Fehlermeldung:

Der Dienst 'MyServiceName' hat keine Anwendungsendpunkte (ohne Infrastruktur). Dies kann daran liegen, dass für Ihre Anwendung keine Konfigurationsdatei gefunden wurde oder dass in der Konfigurationsdatei kein mit dem Dienstnamen übereinstimmendes Dienstelement gefunden wurde oder dass im Dienstelement keine Endpunkte definiert wurden.

Das Problem wurde behoben, indem der Rechtschreibfehler in App.config behoben wurde.

Dale Wilson
quelle
Wählen Sie in VS2015 Debug → Ausnahmeeinstellungen und aktivieren Sie Common Language Runtime Exceptions.
SharpC
1
Warum wurde die ursprüngliche Ausnahme erst gegeben, als Sie den Visual Studio-Debugger verwendet haben?
Jez
2

Ich hatte das gleiche Problem beim Versuch, den Endpunkt des net.tcp wcf-Dienstes in einem http asmx-Dienst zu verwenden.

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

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

Anfangs dachte ich, wenn Sie auf einen Dienst verweisen, wird die Konfigurationsdatei in Bezug auf das Sicherheitstag genauso konfiguriert wie in der Quelle, aber das war nicht der Fall und ich sollte mich manuell darum kümmern. In meinem Fall hatte ich nur

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

Später sah ich, dass der Sicherheitsteil fehlt und es 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"auf meinem Quell-WCF-Dienst verwendet habe und auf dem Client nichts Spezielles hatte, was schlecht war, da die Standardeinstellung transferModeist Bufferedund es wichtig ist, dass sowohl Quelle als auch Client in derselben Konfiguration konfiguriert werden Weg.

ppenchev
quelle
1

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 warten. 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.

Karsten
quelle
1

Wenn Sie diese Meldung in Debug von Visual Studio sehen und die Lösung ein WCF-Projekt enthält. Öffnen Sie dann diese WCF-Projekteinstellungen -> gehen Sie zur Registerkarte "WCF-Optionen" -> deaktivieren Sie die Option "WCF-Service-Host beim Debuggen starten ..."

Horev Ivan
quelle
Ich hatte das gleiche Problem und blieb eine ganze Weile bei diesem Thema hängen. Wahrscheinlich ist es keine gute Praxis, sowohl Client als auch Server auf derselben Lösung zu haben. Danke dir!
Yoosha
1

Für mich wurde das Problem durch eine Konfigurationsdatei verursacht, die beim Importieren der WSDL automatisch erstellt wurde. Ich habe die Bindung von basicHttpBinding auf customBinding aktualisiert. Das Hinzufügen einer zusätzlichen Ausnahmebehandlung hat nicht dazu beigetragen, darauf hinzuweisen.

Vor

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

Nach dem

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

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

Beim Versuch, auf den privaten Schlüssel für die Anmeldeinformationen des TLS-Servers zuzugreifen, ist ein schwerwiegender Fehler aufgetreten. Der vom kryptografischen Modul zurückgegebene Fehlercode lautet 0x8009030D. Der interne Fehlerzustand ist 10001.

Altumano
quelle
0

Dieser Fehler kann auch von Ihrem eigenen Computer ausgelöst werden und ist nicht nur eine nicht behandelte Ausnahme. Wenn die Uhrzeit Ihres Servers / Computers um zu viele Minuten deaktiviert ist, lehnen viele .NET-Webdienste Ihre Anfrage 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 empfangenden Servers korrekt ist. Wenn dies behoben werden muss, müssen Sie Ihren Dienst zurücksetzen oder neu starten, bevor der Kanal wieder geöffnet wird.

Ich habe dieses Problem auf einem Server festgestellt, auf dem die Firewall die Aktualisierung der Internetzeit blockiert hat und der Server aus irgendeinem Grund keine Zeit mehr hat. Alle .NET-Webdienste von Drittanbietern sind fehlerhaft, weil sie jede Webdienstanforderung abgelehnt haben. Das Durchsuchen der Ereignisanzeige half dabei, das Problem zu identifizieren, aber das Einstellen der Uhr löste es. Der Fehler war zu Ende, obwohl wir die Fehlermeldung "Fehlerhafter Status" für zukünftige Webdienstaufrufe erhalten haben.

HBlackorby
quelle
0

Der Server bricht Verbindungen, über die keine Nachricht empfangen wurde, automatisch für die Dauer ab, die dem Empfangszeitlimit entspricht ( Standard ist 10 Minuten ). Dies ist eine DoS-Minderung, um zu verhindern, dass Clients den Server dazu zwingen, Verbindungen auf unbestimmte Zeit offen zu halten.

Da der Server die Verbindung abbricht, weil sie inaktiv ist, erhält der Client diese Ausnahme.

Sie können steuern, wie lange der Server zulässt, dass eine Verbindung inaktiv ist, bevor sie abgebrochen wird, indem Sie das Empfangszeitlimit für die Serverbindung konfigurieren. Bildnachweis: TRVishwanath - MSFT

Vijay Rana
quelle
0

Ich weiß, dass dies ein älterer Beitrag ist, aber eine Sache, auf die Sie achten müssen, wenn Sie die Sicherheit nicht ändern können, ist sicherzustellen, dass Ihr Benutzername und Ihr Passwort festgelegt sind.

Ich hatte einen Dienst mit dem Authentifizierungsmodus UserNameOverTransport. Wenn der Benutzername und das Kennwort für den Dienstclient nicht festgelegt wurden, wird dieser Fehler angezeigt.

Joshua G.
quelle
0

Für mich war es ein Load Balancer / URL-Problem. Ein Webdienst hinter einem Load Balancer hat einen anderen Service hinter demselben Load Balancer aufgerufen und die vollständige URL wie folgt verwendet : loadbalancer.mycompany.com. Ich habe es geändert, um den Load Balancer zu umgehen, wenn ich localhost.mycompany.comstattdessen den zweiten Dienst aufrufe.

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

goku_da_master
quelle
-2

Keine Lösung für dieses Problem, aber wenn bei Ektron eSync der oben genannte Fehler auftritt, ist möglicherweise nicht mehr genügend Speicherplatz in Ihrer Datenbank vorhanden.

Bearbeiten: Tatsächlich handelt es sich nicht nur um ein Problem mit Ektron eSync. Dies kann bei jedem Dienst passieren, der eine vollständige Datenbank abfragt.

Bearbeiten: Wenn Sie nicht genügend Speicherplatz haben oder den Zugriff auf ein Verzeichnis blockieren, das Sie benötigen, tritt dieses Problem auf.

Jonathan Bick
quelle
Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag. Sie können jederzeit Ihre eigenen Beiträge kommentieren. Sobald Sie einen ausreichenden Ruf haben, können Sie jeden Beitrag kommentieren .
Dariusz
2
Ich beantwortete seine Frage "Wie würde ich es lösen?", Es ist nicht meine Schuld, dass er uns nie die Einzelheiten darüber gegeben hat, ob er Ektron verwendet oder nicht. Ich benötige außerdem 50 Mitarbeiter, um seinen Beitrag zu kommentieren.
Jonathan Bick