tags:

views:

2701

answers:

4

Hi there,
I have a client console app talking to a WCF service and I get the following error: "The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error."

I think it's becuase of a contract mismatch but i can't figure out why. The service runs just fine by itself and the 2 parts were working together until i added the impersonation code.

Can anyone see what is wrong?

Here is the client, all done in 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();

And here is the config file of the WCF service:

<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>
A: 

Have you updated the service and not updated the client - that's what the "contract mismatch" really means, typically.

How did you create your client? "Add Service REference" in Visual Studio? Right-click on that reference and choose "Update Reference".

Or what happens if you use the server's app.config file on the client? If you use config on both ends instead of setting everything up in code - does it work then? (the code looks fine, though - I don't see any discrepancies in there....)

Marc

marc_s
Because the client is all done in code I don't need to "update it". Updating the client means writing more code and I don't know what other clode to write? There is no config file for the client, only for the service. I had it working before I added the impersonateCallerForAllOperations=True in the service and AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation the client
i actually get the error on the client side when I call a Method on the service
Can you catch an exception and see what that returns? What type of execption is it? Any more information in there (possibly in the .InnerException property)?
marc_s
It's a System.ServiceModel.CommunicationException, the ex.message is as discribed above and the inner exception is null
A: 

Ok, i've just changed the client so it uses a config file instead of code and I get the same error!

Code:

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

Here is the config file of the client, freshly generated from the Service ... which makes my think that it mightn't be a contract mismatch error

<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>
Yes, probably not - the error message also offers two more possible casuse: "....., a premature session shutdown or an internal server error."
marc_s
+2  A: 

Other possible causes:

  • Trying to serialize an object without a default constructor is a common mistake.
  • Trying to serialize some other kind of non serializable object (such as an Exception). To prevent the item from being serialized apply [IgnoreDataMember] attribute to the field or property.
  • Check your enum fields to make sure they are set to a valid value (or are nullable). You may need to add a 0 value to the enum in some cases. (not sure about fine details of this point).

What to test:

  • Configure WCF tracing for at least critical errors or exceptions. Be careful to watch filesize if you enable any further traces. This will give some very useful information in many cases.

    Just add this under <configuration> in your web.config ON THE SERVER. Create the log directory if it doesn't exist.

<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>
  • Make sure the .svc file will actually come up in a browser without error. This will give you some 'first chance' help. For instance if you have a non serializable object you'll get this message below. Note that it clearly tells you what can't be serialized. Make sure you have 'mex' endpoint enabled and bring up the .svc file in your browser.

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is: System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.DataContractSerializerOperationBehavior contract: http://tempuri.org/%3AIOrderPipelineService ----> System.Runtime.Serialization.InvalidDataContractException: Type 'RR.MVCServices.PipelineStepResponse' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.

Simon_Weaver
+1  A: 

For me, this error message was thrown because my the web.config Service Behavior by default has a low message limit, so when the WCF returned say 200000 bytes and my limit was 64000 bytes the response was truncated and thus you get the "... not meaningful reply". It's meaningful, it's just been truncated and can't be parsed.

I'll paste my web.config change that fixed the issue:

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

The maxItemsInObjectGraph value is the most important!
I hope this helps anyone.

Paul D