Search code examples
c#wcfnettcpbinding

Message oversized on WCF communication


I have a windows service and a winform application that communicate between each other using WCF through TCP.

I sometimes have to exchange huge data and I encountered a CommunicationException on the client. Now I have trouble finding which property to change and where (on the server side or the client side?).

The problem occurs when the server is returning a value to the client that is a 2-uple (my own implementation) of two arrays of doubles: Tuple<Double[], Double[]> (both arrays have always the same length).
I have noticed that there is no error when the arrays have a length of 22 000, but the CommunicationException is thrown when arrays have a length of 44 000.

Here's my App.config file regarding the netTcpBinding part:

  • On the server:

 

<netTcpBinding>
    <binding name="MyBindingConf"
             maxReceivedMessageSize="5000000"
             sendTimeout="00:05:00">
        <readerQuotas maxArrayLength="67108864"
                      maxStringContentLength="67108864"/>
        <security mode="None" />
    </binding>
</netTcpBinding>
  • On the client:

 

<netTcpBinding>
    <binding name="MyBindingConf"
             maxReceivedMessageSize="5000000"
             sendTimeout="00:59:00">
        <readerQuotas maxArrayLength="67108864"
                      maxStringContentLength="67108864"/>
        <security mode="None" />
    </binding>
</netTcpBinding>

Could you point on which property to change and on which side?

P.S: It's not a timeout problem.


EDIT

I have now the same nettcpbindingconfiguration on both server and client:

<bindings>
    <netTcpBinding>
        <binding name="MyBindingConf" 
                 maxReceivedMessageSize="2147483647" 
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 sendTimeout="00:30:00">
            <readerQuotas maxDepth="32" 
                          maxStringContentLength="2147483647" 
                          maxArrayLength="2147483647" 
                          maxBytesPerRead="4096" 
                          maxNameTableCharCount="16384" />
            <security mode="None" />
        </binding>
    </netTcpBinding>
</bindings>

And the same serviceBehavior:

<behaviors>
    <serviceBehaviors>
        <behavior name="Debug">
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
    </serviceBehaviors>
</behaviors>

I then get a NetDispatcherFaultException on the client, advising me to increase maxArrayLength or maxItemsInObjectGraph. But for me, these values are already largely set for what I need to transfer and also set to the max values!

Here's the InnerException message:

The maximum array length quota (19502) or the maximum items in object graph quota has been exceeded while reading XML data. These quotas may be increased by changing the MaxArrayLength property on XmlDictionaryReaderQuotas or the MaxItemsInObjectGraph setting.

Any clue? Where does this 19 502 figure comes from?


Solution

  • On both, the server and client you have to configure the attribute of your binding, if you are exchanging large amounts of data between them. For example:

    <binding name="LargeSettings" maxBufferSize="20000000" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00">
          <readerQuotas maxDepth="32" maxStringContentLength="200000000" maxArrayLength="200000000" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None" />
        </binding>
    

    Work your way from the large values to find the one that suits you.

    EDIT:

    In Client side, you need to configure a behavior, and set that behavior in the client endpoint. Something like this:

    <system.serviceModel>
        <behaviors>
            <endpointBehaviors>
                <behavior name="debug"> <dataContractSerializer maxItemsInObjectGraph="2147483647" />
                </behavior>
            </endpointBehaviors>
        </behaviors>
    

    And you set the behavior in the client endpoint:

    <endpoint name="myEndpoint" behaviorConfiguration="debug">
        Your other settings...
    </endpoint>
    

    Hope this helps.