Maximum Array Length Quota Exception in WCF

8.6k views Asked by At

I am writing a WCF service to upload files but it throws an exceptions when byte array has more than 16384 elements.

This is the exception detail:

The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'CreateDocument'. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 22862.

The config for both client and server sets the maximum array length quota to 2147483647.

Client Config:

<system.serviceModel>
  <bindings>
   <basicHttpBinding>
    <binding name="BasicHttpBinding_IDocumentLibraryService" closeTimeout="00:01:00"
     openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
     allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
     maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
     messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
     useDefaultWebProxy="true">
     <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
      maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
     <security mode="None">
      <transport clientCredentialType="None" proxyCredentialType="None"
       realm="" />
      <message clientCredentialType="UserName" algorithmSuite="Default" />
     </security>
    </binding>
   </basicHttpBinding>
  </bindings>
  <client>
   <endpoint address="http://localhost:50764/DocumentLibraryService.svc"
    binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDocumentLibraryService"
    contract="DocumentLibrary.IDocumentLibraryService" name="BasicHttpBinding_IDocumentLibraryService" />
  </client>

Server Config:

<bindings>

            <basicHttpBinding>
                <binding name="BasicHttpBinding_IDocumentLibraryService" closeTimeout="00:01:00"
                 openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                 allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                 maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                 messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                 useDefaultWebProxy="true">
                    <readerQuotas maxDepth="2147483647"
                maxStringContentLength="2147483647"
                maxArrayLength="2147483647"
                maxBytesPerRead="2147483647"
                maxNameTableCharCount="2147483647" />
                    <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                         realm="" />
                        <message clientCredentialType="UserName" algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <services>

            <service name="BasicHttpBinding_IDocumentLibraryService">

                <clear />
                <endpoint address="mex" binding="mexHttpBinding" name="mex" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" />
                <endpoint binding="basicHttpBinding" name="DocumentLibraryService" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" address=""
                          bindingConfiguration="BasicHttpBinding_IDocumentLibraryService"/>
            </service>
        </services>
2

There are 2 answers

1
Nima M On BEST ANSWER

All I needed to do was to change Service name in web.config file to full service name with namespace:

<service name="SampleNameSpace.DocumentLibraryService">

                <clear />
                <endpoint address="mex" binding="mexHttpBinding" name="mex" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" />
                <endpoint binding="basicHttpBinding" name="DocumentLibraryService" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" address=""
                          bindingConfiguration="BasicHttpBinding_IDocumentLibraryService"/>
            </service>
1
Aliostad On

This is not really an answer since your configuration seems OK. I think you just need to check these values in the code (output to trace or debug) on the service host and the proxy to make sure the same values in config are loaded into your channels.

On possibility is that another threshold is reached and the error is misleading

Now I strongly advise against using byte array to upload files especially if you use XML. These will be represented as XML arrays and the structure will be hugely bloated XML which will take 10 times more than the original file.

I would use:

  • WCF Streaming which works with basic binding as well and is super fast
  • alternatively represent the byte array as base64 string. This will take 33% more space but not 1000%

UPDATE

You can trace the binding name that was used to configure the service (use it inside any of your WCF operations):

public int MyServiceOperation()
{
     Trace.WriteLine(OperationContext.Current.EndpointDispatcher.ChannelDispatcher.BindingName)
....