Sending large byte[] of binary data through WCF – a simple approach

You can send large streams of data through WCF in two ways: by streaming or by buffer. How to enable streaming is discussed here but has the significant restriction that if you stream, you can only have one (yes, 1) parameter into and out of the service. If your goal is just to pass largish objects such as a spreadsheet or a PDF as part of a service operation this could be a significant hurdle to code around.

“By buffer” means that your large data can be handled with no special treatment at all: it is sent, read into memory (the buffer), and processed just like small messages are. You must understand that buffering means the whole message is buffered; As of early 21st century, that fine on most servers for muliti-megabyte data, but not fine for gigabytes of data.

The simple way to handles megabyte messages is to create a binding Configuration with 2 or 3 parameters increased:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="basicHttpFor2MBMessage" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
          <readerQuotas maxArrayLength="2097000" />
        </binding>
      </basicHttpBinding>
    </bindings>

and have your service endpoint use it:

<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpFor2MBMessage" contract="yourContractName>

Voila. You can now send a 2MB large array through SOAP to WCF.

If your large array is binary data, you declare it in your service classes as byte[], which is why you need the maxArrayLength setting. If you are creating test messages by hand or in a testing tool, you also need to know how to represent binary data in a SOAP message.
The usual answer is, use base64 encoding and it should just work, thus:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://MyServiceName">
   <soapenv:Header/>
   <soapenv:Body>
      <dat:Save>
         <dat:Id>111</dat:applicantId>
         <dat:Pdf>JVBE ... <i>base64 encoded string</i> .... JUVPRgo=</dat:contractPdf>
      </dat:Save>
   </soapenv:Body>
</soapenv:Envelope>

Caveats

Security

The WCF default small buffer and message sizes are a guard against DoS attacks so if your service is publicly visible this would leave it less well guarded.

Performance

How fast does your service process large requests?

If (Expected Peak Requests Per Minute) * (Seconds to Process a Request) is bigger than 60 (Seconds in a Minute) then you need more horsepower.

How much memory do you have?

If (Size of Message * Requests per Hour) – (Speed at which WCF frees up an hour’s worth of used buffers) is bigger than your available memory then you’ll fall over. Alas there is no simple setting for ‘Speed at which WCF frees up an hour’s worth of used buffers’ so that calculation is a problem for another blog post. If you might have a problem, you can use PerfMon to watch memory behaviour during a stress test.

Leave a Reply

Your email address will not be published. Required fields are marked *