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.

2 thoughts on “Sending large byte[] of binary data through WCF – a simple approach”

  1. Magnificent goods from you, man. I’ve remember
    your stuff previous to and you are simply too excellent.
    I actually like what you have obtained right here, really like what you are saying and the best way in which you assert it.
    You are making it enjoyable and you continue to care for to keep it smart.
    I can not wait to learn far more from you. That is
    really a great web site.

Leave a Reply

Your e-mail address will not be published. Required fields are marked *