Search code examples
c#wcfwcf-client

WCF Service with large parameters


I've looked at a number of similar topics on SO, but haven't found one that helps with this.

Have a WCF service that takes in XML to process. The XML file I'm reading from is ~600K.

The call works for small xml files (most of the time), but on the larger files I get the error:

System.ServiceModel.Security.MessageSecurityException:
An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.

where the inner exception is:

System.ServiceModel.FaultException:
The message could not be processed. This is most likely because the action 'http://tempuri.org/ISapListener/ProcessSapRoles' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.

Like I say... it works for small files, and my open, send, receive, close, and inactivity timeouts are all set to 10 minutes. It fails in about 20-30 seconds.

Also, the clock on the server and client are perfectly in sync (I've seen that posted as an answer).

My config files as they currently stand (I've played with a lot of settings):

Server:

<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding_Custom" closeTimeout="00:00:10"
             openTimeout="00:01:00" receiveTimeout="00:10:00"
             sendTimeout="00:10:00" bypassProxyOnLocal="false" 
             transactionFlow="false" hostNameComparisonMode="StrongWildcard"
             messageEncoding="Text" textEncoding="utf-8" 
             useDefaultWebProxy="true" allowCookies="false"
             maxReceivedMessageSize="1024768"            
             maxBufferPoolSize="1024768" >
      <readerQuotas maxDepth="32" 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" />
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
<services>
  <service behaviorConfiguration="CSA.GS3.Services.SapListenerBehavior" 
           name="CSA.GS3.Services.SapListener">
    <endpoint address="" binding="wsHttpBinding"  
              bindingConfiguration="wsHttpBinding_Custom" 
              contract="CSA.GS3.Services.ISapListener">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" 
              contract="IMetadataExchange" />
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="CSA.GS3.Services.SapListenerBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

Client:

<bindings>
  <wsHttpBinding>
    <binding name="WSHttpBinding_ISapListener1" 
             closeTimeout="00:10:00" openTimeout="00:10:00" 
             receiveTimeout="00:10:00" sendTimeout="00:10:00"
             bypassProxyOnLocal="false" transactionFlow="false"
             hostNameComparisonMode="StrongWildcard"
             messageEncoding="Text" textEncoding="utf-8" 
             useDefaultWebProxy="true" allowCookies="false"
             maxBufferPoolSize="1024768" 
             maxReceivedMessageSize="1024768">
      <readerQuotas maxDepth="32" 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" />
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
<client>
  <endpoint address="http://gs3-test.us.tycoelectronics.com/SapListener/SapListener.svc"
            binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISapListener1"
            contract="Gs3TestSapListener.ISapListener" 
            name="WSHttpBinding_ISapListener1">
    <identity>
      <dns value="localhost" />
    </identity>
  </endpoint>
</client>

I do have tracing enabled on the service, but I can't make sense out of the log files.

Other exceptions I've received while playing with the config settings:

System.ServiceModel.Security.SecurityNegotiationException
Secure channel cannot be opened because security negotiation with the remote endpoint has failed.

and

System.ServiceModel.ServiceActivationException
The requested service, 'http://../SapListener.svc' could not be activated.


Solution

  • I was able to get this to work with the following configuration:

    Server:

    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpBinding_Custom"
                 closeTimeout="00:10:00"
                 openTimeout="00:10:00"
                 receiveTimeout="00:10:00"
                 sendTimeout="00:10:00"
                 maxReceivedMessageSize="2097152"
                 bypassProxyOnLocal="false" transactionFlow="false" 
                 hostNameComparisonMode="StrongWildcard"
                 maxBufferPoolSize="2097152" messageEncoding="Text"
                 textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
          <readerQuotas maxDepth="32" 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" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    

    Client:

    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_ISapListener1" closeTimeout="00:10:00"
                 openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
                 bypassProxyOnLocal="false" transactionFlow="false" 
                 hostNameComparisonMode="StrongWildcard"
                 maxBufferPoolSize="2097152" 
                 maxReceivedMessageSize="2097152"
                 messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                 allowCookies="false">
          <readerQuotas maxDepth="32" 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" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    

    The only difference I can see is that I bumped up the maxReceivedMessageSize and maxBufferPoolSize... maybe I'm missing something else? If that was the issue, then the problem was that my overhead for the call was adding an additional 400+K to the 600K xml data I was sending