Ronald
terug naar het overzicht

Struggling with WCF maxBufferSize and maxReceivedMessageSize

door Ronald 23-11-2010

The title says it all. I had another encounter with WCF configuration files. About once every two months this just happens. You know you’re going to spend half a day trying to figure out what you are doing wrong and in the end you think: was it really that simple? 

The issue this time was maximum message sizes. I have a WCF service hosted by IIS that returns a list of employees from a database. This works fine if you have less than 500 employees. In this case there were 6000 employees so the client reported a nice error:

 

System.ServiceModel.CommunicationException: The underlying secure session has faulted before the reliable session fully completed. The reliable session was faulted.

 

Not very informative. I added a WCF trace listener to the client. This is as simple as adding the folowing lines to your config file: 

   1: <system.diagnostics>
   2:   <trace autoflush="true" />
   3:   <sources>
   4:     <source name="System.ServiceModel"
   5:             switchValue="Error, ActivityTracing"
   6:             propagateActivity="true">
   7:       <listeners>
   8:         <add name="sdt"
   9:              type="System.Diagnostics.XmlWriterTraceListener"
  10:              initializeData= "c:\ProvisiorLog\client.svclog" />
  11:       </listeners>
  12:     </source>
  13:   </sources>
  14: </system.diagnostics>

  

I opened the log file with svctraceviewer and there was the error message that would solve all our problems:

 The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

A nice and clear error message that tells you how to fix the problem. Simply set maxReceivedMessageSize on the client binding. In my case, the client configuration was generated from the server configuration using svcutil. This means it contains all the default values as well. The binding on the server had the following configuration:

 

   1: <binding name="OrgSyncService_NetTcpBinding"
   2:          portSharingEnabled="true" transactionFlow="true"
   3:          maxReceivedMessageSize="10485760"
   4:          openTimeout="00:01:00" receiveTimeout="00:10:00"
   5:          sendTimeout="00:10:00">
   6:     <security mode="Transport">
   7:         <transport clientCredentialType="Windows"
   8:                    protectionLevel="EncryptAndSign"/>
   9:     </security>
  10:     <readerQuotas maxStringContentLength="10485760" />
  11:     <reliableSession enabled="true"/>
  12: </binding>

 

Generating the configuration on the client using svcutil does not give you the same maxReceivedMessageSize. This makes sense because maybe the server should be allowed to receive really large messages but it never sends large messages back.

 

The generated client configuration looked like this (where I left out some default attributes for better readability). I already updated maxReceivedMessageSize.

 

   1: <binding name="NetTcpBinding_OrgSyncService"
   2:          transactionFlow="true"
   3:          maxBufferSize="65536"
   4:          maxReceivedMessageSize="10485760">
   5:   <reliableSession enabled="true" />
   6:   <security mode="Transport">
   7:     <transport clientCredentialType="Windows"
   8:                protectionLevel="EncryptAndSign" />
   9:   </security>
  10: </binding>

 

If 10MB for maximum received message size isn’t going to fix the problem, then nothing will. Let’s test this. Ok, the client logs the same error message, that’s strange. Let’s take a look at the svc trace log. Also the exact same error message. It still says that we have exceeded our quota of 65536 for incoming messages and we are advised to set maxReceivedMessageSize. But we just increased this to 10MB!

The problem is the maxBufferSize attribute. If you generate a client configuration using svcutil, maxBufferSize is by default set to 65536. A NetTcpBinding defaults to streaming, buffered transfer mode. In this case you should set maxBufferSize equal to maxReceivedMessageSize or not set maxBufferSize at all, in which case it defaults to maxReceivedMessageSize. This doesn't become clear from the documentation (at least I couldn't find it) but taking a look at the MaxBufferSize property (inside ConnectionOrientedTransportBindingElement) via Reflector finally provides some insight:

 

   1: public int MaxBufferSize
   2: {
   3:     get
   4:     {
   5:         if (this.maxBufferSizeInitialized ||
   6:             this.TransferMode != TransferMode.Buffered)
   7:         {
   8:             return this.maxBufferSize;
   9:         }
  10:         long maxReceivedMessageSize = MaxReceivedMessageSize;
  11:         if (maxReceivedMessageSize > 0x7fffffffL)
  12:         {
  13:             return 0x7fffffff;
  14:         }
  15:         return (int) maxReceivedMessageSize;
  16:     }
  17:     set
  18:     {
  19:         this.maxBufferSizeInitialized = true;
  20:         this.maxBufferSize = value;
  21:     }
  22: }

 

So although the error message gave me the impression that there is an easy fix for the problem, it turned out to be a little more difficult.

 

And in the end I also found the piece of documentation that could have told me all along what was the problem. It is all documented on the MaxBufferSize property of ConnectionOrientedTransportBindingElement (unfortunately, you don’t know you have to look there without first checking the source code for NetTcpBinding using Reflector). The documentation for MaxBufferSize reads:

“For streamed messages this property only applies to the message headers; for buffered messages it applies to the entire message.”

Tags:

Development

Reacties

maart 10. 2012 19:35

pingback

Pingback from reykjavik.wordpress.com

Debugging WPF 404 “Bad request” error  « CenterSoftware

reykjavik.wordpress.com

Reactie plaatsen


(Zal uw Gravatar icon tonen)

  Country flag


  • Reactie
  • Live voorbeeld