web-dev-qa-db-fra.com

Problème d'inadéquation des contrats de la WCF

J'ai une application de console client qui parle à un service WCF et le message d'erreur suivant s'affiche: "Le serveur n'a pas fourni de réponse significative; cela pourrait être dû à une non-concordance des contrats, à un arrêt prématuré de la session ou à un serveur interne. Erreur."

Je pense que c'est à cause d'une inadéquation des contrats, mais je ne comprends pas pourquoi. Le service fonctionne très bien par lui-même et les 2 parties travaillaient ensemble jusqu'à ce que j'ajoute le code d'emprunt d'identité. 

Quelqu'un peut-il voir ce qui ne va pas?

Voici le client, tout est fait en code:

NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

EndpointAddress endPoint = new EndpointAddress(new Uri("net.tcp://serverName:9990/TestService1"));
ChannelFactory<IService1> channel = new ChannelFactory<IService1>(binding, endPoint);
channel.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
IService1 service = channel.CreateChannel();

Et voici le fichier de configuration du service WCF:

<configuration>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="MyBinding">
          <security mode="Message">
            <transport clientCredentialType="Windows"/>
            <message clientCredentialType="Windows" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCFTest.ConsoleHost2.Service1Behavior">
          <serviceMetadata httpGetEnabled="true"  />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization impersonateCallerForAllOperations="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="WCFTest.ConsoleHost2.Service1Behavior"
          name="WCFTest.ConsoleHost2.Service1">
        <endpoint address="" binding="wsHttpBinding" contract="WCFTest.ConsoleHost2.IService1">
          <identity>
            <dns value="" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <endpoint binding="netTcpBinding" bindingConfiguration="MyBinding"
            contract="WCFTest.ConsoleHost2.IService1" />
        <Host>
          <baseAddresses>
            <add baseAddress="http://serverName:9999/TestService1/" />
            <add baseAddress="net.tcp://serverName:9990/TestService1/" />
          </baseAddresses>
        </Host>
      </service>
    </services>
  </system.serviceModel>
</configuration>
16
Tom

Autres causes possibles:

  • Essayer de sérialiser un objet sans constructeur par défaut.
  • Essayer de sérialiser un autre type d'objet non sérialisable (tel qu'une exception). Pour empêcher la sérialisation de l'élément, appliquez l'attribut [IgnoreDataMember] au champ ou à la propriété.
  • Vérifiez vos champs enum pour vous assurer qu'ils sont définis sur une valeur valide (ou qu'ils sont nullables). Vous devrez peut-être ajouter une valeur 0 à l'énumération dans certains cas. (pas sûr des détails fins de ce point).

Ce qu'il faut tester:

  • Configurez le suivi WCF pour au moins les erreurs critiques ou les exceptions. Veillez à regarder la taille du fichier si vous activez d'autres traces. Cela vous donnera des informations très utiles dans de nombreux cas.

    Ajoutez simplement ceci sous <configuration> dans votre web.config SUR LE SERVEUR . Créez le répertoire log s'il n'existe pas.

 <system.diagnostics>
     <sources>
       <source name="System.ServiceModel"
               switchValue="Error, Critical"
               propagateActivity="true">
         <listeners>
           <add name="traceListener"
               type="System.Diagnostics.XmlWriterTraceListener"
               initializeData= "c:\log\WCF_Errors.svclog" />
         </listeners>
       </source>
     </sources>
   </system.diagnostics>
  • Assurez-vous que le fichier .svc apparaîtra dans un navigateur sans erreur. Cela vous donnera une aide de première chance. Par exemple, si vous avez un objet non sérialisable, vous recevrez ce message ci-dessous. Notez qu'il indique clairement ce qui ne peut pas être sérialisé. Assurez-vous que le point de terminaison 'mex' est activé et ouvrez le fichier .svc dans votre navigateur.

Un ExceptionDetail, probablement créé par IncludeExceptionDetailInFaults = true, Et dont la valeur est: System.InvalidOperationException: une exception a été émise lors d'un appel à une extension D'exportation WSDL. : System.ServiceModel.Description.DataContractSerializerOperationBehavior Contrat: http://tempuri.org/:IOrderPipelineService ----> System.Runtime.Serialization. InvalidDataContractException: Tapez 'RR.MVCServices.PipelineStepResponse' Ne peut pas être sérialisé. Pensez à marquer Avec l'attribut DataContractAttribute Et à marquer tous les membres Que vous souhaitez sérialiser avec l'attribut DataMemberAttribute. 

32
Simon_Weaver

Pour moi, ce message d'erreur a été émis parce que mon comportement de service web.config par défaut a une limite de message faible. Ainsi, lorsque la fonction WCF a renvoyé 200 000 octets et que ma limite était de 64 000 octets, la réponse a été tronquée et vous obtenez le caractère ".. réponse non significative ". C'est significatif, il vient d'être tronqué et ne peut pas être analysé. 

Je vais coller mon changement web.config qui a résolu le problème: 

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="YourNameSpace.DataServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      <serviceTimeouts transactionTimeout="05:05:00" />
      <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500"
       maxConcurrentInstances="2147483647" />
</behavior>
</serviceBehaviors>
</behaviors>

La valeur maxItemsInObjectGraph est la plus importante!
J'espère que cela aidera n'importe qui.

8
Paul D

J'avais un problème similaire. Après avoir passé deux heures à réfléchir et tenter de trouver une réponse en ligne, j'ai décidé de suivre l'approche consistant à séraliser et à désérialiser la valeur/l'objet de retour côté serveur à l'aide de System.Runtime.Serialization.DataContractSerializer et a finalement conclu que avait manqué d'ajouter l'attribut EnumMember sur l'un des Enums.

Vous pouvez être confronté à un problème similaire.

Voici l'extrait de code qui m'a aidé à résoudre le problème:

      var dataContractSerializer = new System.Runtime.Serialization.DataContractSerializer(typeof(MyObject));
      byte[] serializedBytes;
        using (System.IO.MemoryStream mem1 = new System.IO.MemoryStream())
        {
            dataContractSerializer.WriteObject(mem1, results);
            serializedBytes = mem1.ToArray();
        }

        MyObject deserializedResult;
        using (System.IO.MemoryStream mem2 = new System.IO.MemoryStream(serializedBytes))
        {
            deserializedResult = (MyObject)dataContractSerializer.ReadObject(mem2);
        }
2
Varun Bedi

Ok, je viens de changer le client afin qu'il utilise un fichier de configuration au lieu du code et je reçois la même erreur!

Code:

ServiceReference1.Service1Client client = new WCFTest.ConsoleClient.ServiceReference1.Service1Client("NetTcpBinding_IService1");    
client.PrintMessage("Hello!");

Voici le fichier de configuration du client, fraîchement généré à partir du service ... ce qui me fait penser que cela pourrait ne pas être une erreur d’incompatibilité de contrat

<configuration>
    <system.serviceModel>
        <bindings>
            <netTcpBinding>
                <binding name="NetTcpBinding_IService1" 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="10"
                    maxReceivedMessageSize="65536">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                        <message clientCredentialType="Windows" />
                    </security>
                </binding>
            </netTcpBinding>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IService1" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" establishSecurityContext="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://servername:9999/TestService1/" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
                name="WSHttpBinding_IService1">
                <identity>
                    <dns value="&#xD;&#xA;          " />
                </identity>
            </endpoint>
            <endpoint address="net.tcp://serverName:9990/TestService1/" binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_IService1" contract="ServiceReference1.IService1"
                name="NetTcpBinding_IService1">
                <identity>
                    <userPrincipalName value="MyUserPrincipalName " />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>
1
Tom

Si vous avez deux méthodes avec le même nom et les mêmes paramètres dans votre WCF, cette erreur sera renvoyée.

0
sivaprakash