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 ;)

 



Shawn
Shawn Wildermuth
Author, Teacher, and Coach




My Courses

Wilder Minds Training
Vue.js by Example (New Lower Price)
Bootstrap 4 by Example (New Lower Price)
Intro to Font Awesome 5 (Free Course)
Pluralsight
Building an API with ASP.NET Core (New Course)
Building a Web App with ASP.NET Core, MVC6, EF Core, Bootstrap and Angular (updated for 2.2)
Less: Getting Started (New)
Using Visual Studio Code for ASP.NET Core Projects
Implementing ASP.NET Web API

Application Name WilderBlog Environment Name Production
Application Ver v4.0.30319 Runtime Framework x86
App Path D:\home\site\wwwroot\ Runtime Version .NET Core 4.6.27617.04
Operating System Microsoft Windows 10.0.14393 Runtime Arch X86