Schnelleinstieg zur Problembehandlung in WCF

In diesem Thema wird eine Reihe bekannter Probleme aufgeführt, denen Kunden beim Entwickeln von WCF-Clients und -Diensten begegnet sind. Wenn Ihr spezifisches Problem nicht in dieser Liste enthalten ist, sollten Sie die Ablaufverfolgung für den Dienst konfigurieren. Dadurch wird eine Ablaufverfolgungsdatei generiert, die Sie im Ablaufverfolgungsdatei-Viewer anzeigen können, um detaillierte Informationen zu Ausnahmen im Dienst zu erhalten. Weitere Informationen zum Konfigurieren der Ablaufverfolgung finden Sie unter Configuring Tracing. Weitere Informationen zum Ablaufverfolgungsdatei-Viewer finden Sie unter Service Trace Viewer Tool (SvcTraceViewer.exe).

  1. Wenn ich nach dem Installieren von Windows 7 und IIS versuche, auf einen WCF-Dienst zuzugreifen, erhalte ich die folgende Fehlermeldung: HTTP-Fehler 404.3 – Nicht gefunden.

    HTTP Fehler 404.3 – Nicht gefunden. Die angeforderte Seite kann aufgrund einer Konfigurationserweiterung nicht angezeigt werden. Wenn es sich bei der Seite um ein Skript handelt, müssen Sie einen Handler hinzufügen. Wenn die Datei heruntergeladen werden soll, müssen Sie eine MIME-Zuordnung hinzufügen. Detaillierte Fehlerinformationen finden Sie unter dem Modul StaticFileModule.

  2. Manchmal wird eine MessageSecurityException bei der zweiten Anforderung ausgelöst, wenn sich der Client nach der ersten Anforderung eine Weile im Leerlauf befunden hat. Was passiert?

  3. Der Dienst lehnt nach einer Interaktion mit ungefähr 10 Clients weitere Clients ab. Was passiert?

  4. Kann ich die Dienstkonfiguration aus einer anderen Quelle laden als der Konfigurationsdatei der WCF-Anwendung?

  5. Dienst und Client funktionieren hervorragend, nicht jedoch, wenn sich der Client auf einem anderen Computer befindet. Woran liegt das?

  6. Beim Auslösen einer FaultException<Ausnahme>, deren Typ eine Ausnahme ist, erhalte ich immer einen allgemeinen FaultException-Typ auf dem Client, nicht den generischen Typ. Woran liegt das?

  7. Unidirektionale und Anforderung-Antwort-Vorgänge scheinen nahezu mit der gleichen Geschwindigkeit zurückgegeben zu werden, wenn die Antwort keine Daten enthält. Woran liegt das?

  8. Ich verwende ein X.509-Zertifikat mit dem Dienst und erhalte eine System.Security.Cryptography.CryptographicException. Woran liegt das?

  9. Ich habe den ersten Parameter eines Vorgangs von Groß- in Kleinbuchstaben geändert, und der Client löst nun eine Ausnahme aus. Woran liegt das?

  10. Bei der Verwendung eines meiner Ablaufverfolgungstools wird EndpointNotFoundException ausgelöst. Woran liegt das?

  11. Beim Aufruf einer WCF-Web HTTP-Anwendung aus einer WCF-SOAP-Anwendung gibt der Dienst die folgende Fehlermeldung zurück: 405 "Method Not Allowed"

Was ist die Basisadresse? Worin besteht die Beziehung zu einer Endpunktadresse?

Wenn ich nach dem Installieren von Windows 7 und IIS versuche, auf einen WCF-Dienst zuzugreifen, erhalte ich die folgende Fehlermeldung: HTTP-Fehler 404.3 – Nicht gefunden.

Die vollständige Fehlermeldung lautet:

HTTP Fehler 404.3 – Nicht gefunden. Die angeforderte Seite kann aufgrund einer Konfigurationserweiterung nicht angezeigt werden. Wenn es sich bei der Seite um ein Skript handelt, müssen Sie einen Handler hinzufügen. Wenn die Datei heruntergeladen werden soll, müssen Sie eine MIME-Zuordnung hinzufügen. Detaillierte Fehlerinformationen finden Sie unter dem Modul StaticFileModule.

Diese Fehlermeldung wird ausgegeben, wenn in der Systemsteuerung „Windows Communication Foundation-HTTP-Aktivierung“ nicht explizit festgelegt ist. Um diese Einstellung festzulegen, wechseln Sie zur Systemsteuerung, und klicken Sie in der linken unteren Ecke des Fensters auf „Programme“. Klicken Sie auf "Windows-Funktionen ein- oder ausschalten". Erweitern Sie "Microsoft .NET Framework 3.5.1", und wählen Sie "Windows Communication Foundation-Http-Aktivierung" aus.

Manchmal wird eine MessageSecurityException bei der zweiten Anforderung ausgelöst, wenn sich der Client nach der ersten Anforderung eine Weile im Leerlauf befunden hat. Was passiert?

Die zweite Anforderung kann in erster Linie aus zwei Gründen fehlschlagen: (1) Das Timeout der Sitzung wurde überschritten. (2) Der Webserver, der diesen Dienst hostet, wird wiederverwendet. Im ersten Fall ist die Sitzung so lange gültig, bis das Timeout des Diensts überschritten wird. Wenn der Dienst innerhalb des Zeitrahmens, der in der Bindung des Dienstes angegeben ist (ReceiveTimeout), keine Anforderung vom Client erhält, beendet der Dienst die Sicherheitssitzung. Nachfolgende Clientnachrichten führen zu MessageSecurityException. Der Code muss erneut eine Sicherheitssitzung mit dem Dienst herstellen, um weitere Nachrichten senden oder ein Token für den Sicherheitszustandskontext verwenden zu können. Token für den Sicherheitszustandskontext sorgen auch dafür, dass eine Sicherheitssitzung das Wiederverwenden eines Webservers überdauert. Weitere Informationen zur Verwendung von Token für den Sicherheitszustandskontext finden Sie unter Vorgehensweise: Erstellen eines Tokens für den Sicherheitskontext einer sicheren Sitzung. Stattdessen können Sie Sicherheitssitzungen auch deaktivieren. Wenn Sie die <wsHttpBinding>-Bindungen verwenden, können Sie die establishSecurityContext-Eigenschaft auf false festlegen, um sichere Sitzungen zu deaktivieren. Wenn Sie Sicherheitssitzungen für andere Bindungen deaktivieren möchten, müssen Sie eine benutzerdefinierte Bindung erstellen. Ausführliche Informationen zum Erstellen einer benutzerdefinierten Bindung finden Sie unter How to: Create a Custom Binding Using the SecurityBindingElement. Bevor Sie eine dieser Optionen anwenden, müssen Sie die Sicherheitsanforderungen der Anwendung kennen.

Der Dienst lehnt nach einer Interaktion mit ungefähr 10 Clients weitere Clients ab. Was passiert?

Standardmäßig können Dienste nur 10 Sitzungen gleichzeitig verarbeiten. Wenn die Dienstbindungen Sitzungen verwenden, akzeptiert der Dienst neue Clientverbindungen folglich, bis diese Zahl erreicht ist. Anschließend lehnt er neue Clientverbindungen ab, bis eine der aktuellen Sitzungen beendet wird. Es gibt verschiedene Möglichkeiten, mehr Clients zu unterstützen. Wenn der Dienst keine Sitzungen erfordert, verwenden Sie keine sitzungsbasierte Bindung. (Weitere Informationen finden Sie unter Verwenden von Sitzungen.) Sie können auch das Sitzungslimit erhöhen, indem Sie den Wert der MaxConcurrentSessions-Eigenschaft auf eine Zahl festlegen, die Ihren Anforderungen entspricht.

Kann ich die Dienstkonfiguration aus einer anderen Quelle laden als der Konfigurationsdatei der WCF-Anwendung?

Ja. Sie müssen jedoch eine benutzerdefinierte ServiceHost -Klasse erstellen, die die ApplyConfiguration -Methode überschreibt. In dieser Methode können Sie die Basisklasse aufrufen und zuerst die Konfiguration laden (wenn Sie die Standardkonfigurationsinformationen ebenfalls laden möchten). Sie können jedoch auch das gesamte Konfigurationsladesystem ersetzen. Falls Sie eine Konfiguration aus einer anderen Konfigurationsdatei als der Anwendungskonfigurationsdatei laden möchten, müssen Sie die Konfigurationsdatei selbst analysieren und die Konfiguration laden.

Im folgenden Codebeispiel wird veranschaulicht, wie die ApplyConfiguration -Methode überschrieben und ein Endpunkt direkt konfiguriert wird.

public class MyServiceHost : ServiceHost  
{  
    public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
      : base(serviceType, baseAddresses)  
    {
        Console.WriteLine("MyServiceHost Constructor");
    }  
  
    protected override void ApplyConfiguration()  
    {  
        string straddress = GetAddress();  
        Uri address = new Uri(straddress);  
        Binding binding = GetBinding();  
        base.AddServiceEndpoint(typeof(IData), binding, address);  
    }  
  
    string GetAddress()  
    {
        return "http://MyMachine:7777/MyEndpointAddress/";
    }  
  
    Binding GetBinding()  
    {  
        WSHttpBinding binding = new WSHttpBinding();  
        binding.Security.Mode = SecurityMode.None;  
        return binding;  
    }  
}  

Dienst und Client funktionieren hervorragend, nicht jedoch, wenn sich der Client auf einem anderen Computer befindet. Woran liegt das?

Je nach Ausnahme können verschiedene Probleme vorliegen:

  • Möglicherweise müssen Sie die Clientendpunktadressen von localhost auf den Hostnamen ändern.

  • Sie müssen gegebenenfalls den Anschluss zur Anwendung öffnen. Weitere Informationen finden Sie unter Firewall Instructions in den SDK-Beispielen.

  • Informationen zu weiteren möglichen Problemen finden Sie im Thema mit den Beispielen unter Durchführen der Windows Communication Foundation-Beispiele.

  • Wenn der Client Windows-Anmeldeinformationen verwendet und es sich bei der Ausnahme um SecurityNegotiationExceptionhandelt, konfigurieren Sie Kerberos wie folgt.

    1. Fügen Sie die Anmeldeinformationen für die Identität dem Endpunktelement in der Datei App.config des Clients hinzu:

      <endpoint
        address="http://MyServer:8000/MyService/"
        binding="wsHttpBinding"
        bindingConfiguration="WSHttpBinding_IServiceExample"
        contract="IServiceExample"
        behaviorConfiguration="ClientCredBehavior"
        name="WSHttpBinding_IServiceExample">  
        <identity>  
          <userPrincipalName value="name@corp.contoso.com"/>  
        </identity>  
      </endpoint>  
      
    2. Führen Sie den selbst gehosteten Dienst unter dem System- oder dem Netzwerkdienstkonto aus. Sie können diesen Befehl ausführen, um unter dem Systemkonto ein Befehlsfenster zu erstellen:

      at 12:36 /interactive "cmd.exe"  
      
    3. Hosten Sie den Dienst unter Internetinformationsdienste (IIS). Standardmäßig wird hier das Dienstprinzipalnamenkonto verwendet.

    4. Registrieren Sie mit SetSPN einen neuen Dienstprinzipalnamen bei der Domäne. Dazu müssen Sie ein Domänenadministrator bzw. eine Domänenadministratorin sein.

Weitere Informationen zu Kerberos-Protokoll finden Sie unter In WCF verwendete Sicherheitsbegriffe sowie hier:

Beim Auslösen einer FaultException<Ausnahme>, deren Typ eine Ausnahme ist, erhalte ich immer einen allgemeinen FaultException-Typ auf dem Client, nicht den generischen Typ. Woran liegt das?

Erstellen Sie unbedingt einen eigenen benutzerdefinierten Fehlerdatentyp und deklarieren Sie ihn als Detailtyp in ihrem Fehlervertrag. Das Problem entsteht, weil Folgendes geschieht, wenn vom System bereitgestellter Ausnahmetypen verwendet werden:

  • Eine Typabhängigkeit wird erstellt, die eine der größten Stärken dienstorientierter Anwendungen entfernt.

  • Ausnahmen werden nicht notwendigerweise standardmäßig serialisiert. Einige – wie SecurityException– sind vielleicht überhaupt nicht serialisierbar.

  • Interne Implementierungsdetails werden für Clients verfügbar gemacht. Weitere Informationen finden Sie unter Angeben und Behandeln von Fehlern in Verträgen und Diensten.

Wenn Sie eine Anwendung debuggen, können Sie jedoch mit der ServiceDebugBehavior -Klasse Ausnahmeinformationen serialisieren und an den Client zurückgeben.

Unidirektionale und Anforderung-Antwort-Vorgänge scheinen nahezu mit der gleichen Geschwindigkeit zurückgegeben zu werden, wenn die Antwort keine Daten enthält. Woran liegt das?

Einen Vorgang als unidirektional anzugeben, bedeutet, dass der Vorgangsvertrag lediglich eine Eingabenachricht akzeptiert und keine Ausgabenachricht zurückgibt. In WCF werden alle Clientaufrufe zurückgegeben, wenn die ausgehenden Daten zur Übertragung geschrieben wurden oder eine Ausnahme ausgelöst wurde. Unidirektionale Vorgänge funktionieren genauso. Außerdem können sie eine Ausnahme auslösen, falls der Dienst nicht gefunden wird, oder sie können blockiert werden, falls der Dienst nicht zur Annahme der Daten aus dem Netzwerk bereit ist. In der Regel führt dies in WCF zu unidirektionalen Aufrufen, die schneller an den Client zurückgegeben werden als Anforderung-Antwort-Vorgänge. Allerdings verlangsamt jede Bedingung, die das Senden der ausgehenden Daten über das Netzwerk verlangsamt, unidirektionale Vorgänge ebenso wie Anforderung-Antwort-Vorgänge. Weitere Informationen finden Sie unter Unidirektionale Dienste sowie unter Zugreifen auf Dienste mithilfe eines WCF-Clients.

Ich verwende ein X.509-Zertifikat mit dem Dienst und erhalte eine System.Security.Cryptography.CryptographicException. Woran liegt das?

Das Problem tritt in der Regel nach einer Änderung des Benutzerkontos auf, unter dem der IIS-Arbeitsprozess ausgeführt wird. Wenn Sie beispielsweise in Windows XP das Standardbenutzerkonto, unter dem die Datei „Aspnet_wp.exe“ ausgeführt wird, von ASP.NET in ein benutzerdefiniertes Konto ändern, wird ggf. dieser Fehler angezeigt. Bei der Verwendung eines privaten Schlüssels benötigt der entsprechende Prozess die Berechtigungen für den Zugriff auf die Datei, in der der Schlüssel gespeichert ist.

In diesem Fall müssen Sie dem Konto des Prozesses Leseberechtigungen für die Datei mit dem Schlüssel erteilen. Wenn z. B. der IIS-Arbeitsprozess unter dem Konto Bob ausgeführt wird, müssen Sie Bob den Lesezugriff auf die Datei erteilen, die den privaten Schlüssel enthält.

Weitere Informationen zur Vorgehensweise beim Erteilen der richtigen Zugriffsrechte für das Benutzerkonto auf die Datei, die den privaten Schlüssel für ein bestimmtes X.509-Zertifikat enthält, finden Sie unter Vorgehensweise: Zugänglichmachen von X.509-Zertifikaten für WCF.

Ich habe den ersten Parameter eines Vorgangs von Groß- in Kleinbuchstaben geändert, und der Client löst nun eine Ausnahme aus. Woran liegt das?

Die Werte der Parameternamen in der Vorgangssignatur sind Teil des Vertrags, und die Groß- und Kleinschreibung wird beachtet. Verwenden Sie das System.ServiceModel.MessageParameterAttribute -Attribut, wenn der lokale Parametername von den Metadaten unterschieden werden muss, die den Vorgang für Clientanwendungen beschreiben.

Bei der Verwendung eines meiner Ablaufverfolgungstools wird EndpointNotFoundException ausgelöst. Woran liegt das?

Wenn Sie ein anderes Ablaufverfolgungstool als den vom System bereitgestellten WCF-Ablaufverfolgungsmechanismus verwenden und EndpointNotFoundException ausgelöst wird, ist ein Adressfilterkonflikt aufgetreten. Verweisen Sie die Nachrichten in diesem Fall mithilfe der ClientViaBehavior-Klasse auf das Ablaufverfolgungstool, und lassen Sie das Tool diese Nachrichten an die Dienstadresse weiterleiten. Die ClientViaBehavior -Klasse ändert den Adressierungsheader Via und gibt die nächste Netzwerkadresse unabhängig vom endgültigen Empfänger an, der mit dem Adressierungsheader To angegeben wird. Ändern Sie dabei jedoch nicht die Endpunktadresse, die den To -Wert festlegt.

Das folgende Codebeispiel zeigt eine standardmäßige Konfigurationsdatei für einen Beispielclient.

<endpoint
  address="http://localhost:8000/MyServer/"  
  binding="wsHttpBinding"  
  bindingConfiguration="WSHttpBinding_IMyContract"  
  behaviorConfiguration="MyClient"
  contract="IMyContract"
  name="WSHttpBinding_IMyContract">  
</endpoint>  
<behaviors>  
  <endpointBehaviors>  
    <behavior name="MyClient">  
      <clientVia viaUri="http://localhost:8001/MyServer/"/>  
    </behavior>  
  </endpointBehaviors>  
</behaviors>  

Was ist die Basisadresse? Worin besteht die Beziehung zu einer Endpunktadresse?

Eine Basisadresse ist die Stammadresse für eine ServiceHost -Klasse. Wenn Sie der Dienstkonfiguration eine ServiceMetadataBehavior -Klasse hinzufügen, werden standardmäßig die WSDL (Web Services Description Language) für alle vom Host veröffentlichten Endpunkte aus der HTTP-Basisadresse und alle relativen Adressen, die für das Metadatenverhalten bereitgestellt werden, sowie "?wsdl" abgerufen. Wenn Sie mit ASP.NET und IIS vertraut sind, ist die Basisadresse mit dem virtuellen Verzeichnis vergleichbar.

Gemeinsames Verwenden eines Ports durch einen Dienstendpunkt und einen mex-Endpunkt mithilfe der NetTcpBinding

Wenn Sie die Basisadresse für einen Dienst als net.tcp://MyServer:8080/MyService angeben und die folgenden Endpunkte hinzufügen:

<services>  
  <service name="Microsoft.Samples.NetTcp.CalculatorService">  
    <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>  
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />  
  </service>  
</services>  

Und wenn Sie eine der NetTcpBinding-Einstellungen wie im folgenden Konfigurationsausschnitt veranschaulicht ändern:

<bindings>  
  <netTcpBinding>  
    <binding closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="11" maxReceivedMessageSize="65536">  
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>  
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>  
      <security mode="Transport">  
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>  
      </security>  
    </binding>  
  </netTcpBinding>  
</bindings>  

Ein Fehler ähnlich dem folgenden wird angezeigt: Unbehandelte Ausnahme: System.ServiceModel.AddressAlreadyInUseException: Für den IP-Endpunkt 0.0.0.0:9000 ist bereits ein Listener vorhanden. Sie können diesen Fehler beheben, indem Sie eine vollqualifizierte URL mit einem anderen Port für den MEX-Endpunkt angeben. Dies wird im folgenden Konfigurationsausschnitt veranschaulicht:

<services>  
  <service name="Microsoft.Samples.NetTcp.CalculatorService">  
    <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>  
    <endpoint address="net.tcp://localhost:9001/servicemodelsamples/mex" binding="mexTcpBinding" contract="IMetadataExchange" />  
  </service>  
</services>  

Beim Aufruf einer WCF-Web HTTP-Anwendung aus einer WCF-SOAP-Anwendung gibt der Dienst die folgende Fehlermeldung zurück: 405 "Method Not Allowed"

Das Aufrufen einer WCF-Web-HTTP-Anwendung (ein Dienst, der WebHttpBinding und WebHttpBehavior verwendet) aus einem WCF-Dienst kann zu folgender Ausnahme führen: Unhandled Exception: System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: The remote server returned an unexpected response: (405) Method Not Allowed. Diese Ausnahme tritt auf, weil WCF den ausgehenden Vorgangskontext (OperationContext) mit dem eingehenden Vorgangskontext (OperationContext) überschreibt. Um dieses Problem zu beheben, erstellen Sie im WCF-Web-HTTP-Dienstvorgang einen Vorgangskontextbereich (OperationContextScope). Beispiel:

public string Echo(string input)  
{  
    using (new OperationContextScope(this.InnerChannel))  
    {  
        return base.Channel.Echo(input);  
    }  
}  

Siehe auch