Using Large Message Requests in Silverlight with WCF

SilverlightToday I was working with a client and ran into a problem I didn't expect. This particular problem had to do with Silverlight consuming a WCF Service. Sometimes WCF causes me to spew four letter words. There is a class of WCF problems that cause this: connection rejection. WCF has been designed to prevent common DDoS and other attacks that could cause servers to fail or at least not serve honest requests. To this end the default size of a request is quite small. In fact, its usually 64K in size. This size is fine for most every request but occassionally when a client wants to send a collection of things to the server this size is too small. But we'll get to that in a minute. First, some background...

This particular client has a large service that's been working for quite a while, then suddenly a single call he has was being rejected. The new service call he was making was sending back a list of a couple of hundred of POCO classes. He had been downloading large lists before so on the surface this should have worked. But it didn't. 

The cause was that the default WCF limits were rejecting the connection. This type of error where its just failing, even Fiddler isn't helpful. There is no return code, the connection is just severed. Debugging it requires some trial and error which sucks.  The calls that were returning a lot of data were working fine because the default ClientConfig file looks like this:

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="CustomBinding_MyService">
          <binaryMessageEncoding />
          <httpTransport maxReceivedMessageSize="2147483647"
                       maxBufferSize="2147483647">
            <extendedProtectionPolicy policyEnforcement="Never" />
          </httpTransport>
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://127.0.0.1.:8000/MyService.svc"
                binding="customBinding"
                bindingConfiguration="CustomBinding_MyService"
                contract="MyServices.MyService"
                name="CustomBinding_MyService" />
    </client>
  </system.serviceModel>
</configuration>

The maxReceivedMessageSize and maxBufferSize both accept these large responses from the server. But the reverse isn't true. The server's defaults are about 64K. Since we got it working, I wanted to show what we did so maybe others could use these server settings to address it.

The trick is to change the customBinding in the web.config to use larger defaults. I picked 2MB as it its a reasonable size. Of course setting them to 2GB like shown above will work but it does leave you more vulnerable to attacks.  Pick a size that isn't larger than your largest request but isn't overly large. Its a guessing game.  To set these, you need to add them to your web.config is to put them on the httpTransport node:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="TestLargeWCF.Web.MyServiceBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="false"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <customBinding>
      <binding name="customBinding0">
        <binaryMessageEncoding />
        <httpTransport maxReceivedMessageSize="2097152"
                     maxBufferSize="2097152" 
                     maxBufferPoolSize="2097152" />
      </binding>
    </customBinding>
  </bindings>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  <services>
    <service behaviorConfiguration="Web.MyServiceBehavior"
             name="TestLargeWCF.Web.MyService">
      <endpoint address=""
                binding="customBinding"
                bindingConfiguration="customBinding0"
                contract="TestLargeWCF.Web.MyService"/>
      <endpoint address="mex"
                binding="mexHttpBinding"
                contract="IMetadataExchange"/>
    </service>
  </services>
</system.serviceModel>

That's the trick. Hope it helps you not waste your day like I wasted mine ;)

 

 

Comments

Gravatar

Danijel Stulic Friday, September 11, 2009

I've ran on this on more occasions, and is easily discovered via WCF Trace Log:
http://msdn.microsoft.com/en-us/library/ms732023.aspx
http://msdn.microsoft.com/en-us/library/cc949006.aspx

Gravatar

Ken Monday, September 14, 2009

yep. everybody i know who has used WCF has run into max____size problems at one point or another.

Gravatar

Giovanny Fernandez Friday, September 18, 2009

It is very important to set aditionally de readerquotas atributes on the httptransport bindingelement.

Gravatar

Bill Brock Friday, September 18, 2009

Thanks, this solved a big problem in our app. Keep the great info coming.

Gravatar

Rajib Seth Thursday, July 29, 2010

Thanks , it's working in my case also.

Gravatar

Nick Saturday, August 7, 2010

Have you tried to pass anything larger than 4194304 bytes?
It seems that any value larger than 4194304 makes no difference so the maximum is not 2147483647.

Gravatar

Aditya Thursday, December 30, 2010

i follow your steps but still i am getting this error. Please help us.

WCF – System.ServiceModel.ProtocolException was caught. Message=”The remote server returned an unexpected response: (400) Bad Request.”

Gravatar

Dan Wednesday, March 30, 2011

Thanx Shawn...I found several similar posts that did not work for me...but this saved me a prison stay!

Gravatar

RG Wednesday, June 1, 2011

This post saved me a lot of time and some hair :)

Thanks.

Gravatar

GarfieldJiang Thursday, October 18, 2012

Thanks for your post,it's really helpful.

Gravatar

Valon Bajrami Wednesday, June 5, 2013

Thank you ... Thank you ... Thank you so much for your solution ....

Gravatar

Ajay Tuesday, October 8, 2013

I have tried you code. I have changed my web.config and ServiceReferences.ClientConfig. But my problem is not solved. I am getting the same error after using this.

Error :

An exception of type 'System.ServiceModel.CommunicationException' occurred in System.ServiceModel.ni.dll but was not handled in user code

Inner Exception : The remote server returned an error: NotFound.

Gravatar

Shawn Wildermuth Tuesday, October 8, 2013

Ajay, NotFound is a generic exception passed back from browser. Can you debug it on the server?


Leave a Comment

*
*
*