Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Streaming binary data to WCF rest service gives Bad Request (400) when content length exceeds 64k

I have a WCF service that takes a stream:

[ServiceContract]
public class UploadService : BaseService
{
    [OperationContract]
    [WebInvoke(BodyStyle=WebMessageBodyStyle.Bare, Method=WebRequestMethods.Http.Post)]
    public void Upload(Stream data)
    {
        // etc.         
    }
}

This method is to allow my Silverlight application to upload large binary files, the easiest way being to craft the HTTP request by hand from the client. Here is the code in the Silverlight client that does this:

const int contentLength = 64 * 1024;  // 64 Kb

var request = (HttpWebRequest)WebRequest.Create("http://localhost:8732/UploadService/");
request.AllowWriteStreamBuffering = false;
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/octet-stream";
request.ContentLength = contentLength;
using (var outputStream = request.GetRequestStream())
{
     outputStream.Write(new byte[contentLength], 0, contentLength);
     outputStream.Flush();
     using (var response = request.GetResponse());
}

Now, in the case above, where I am streaming 64 kB of data (or less), this works OK and if I set a breakpoint in my WCF method, and I can examine the stream and see 64 kB worth of zeros - yay!

The problem arises if I send anything more than 64 kB of data, for instance by changing the first line of my client code to the following:

const int contentLength = 64 * 1024 + 1; // 64 kB + 1 B

This now throws an exception on the client when I call request.GetResponse():

The remote server returned an error: (400) Bad Request.

In the server's WCF configuration I have set maxReceivedMessageSize, maxBufferSize and maxBufferPoolSize to 2147483647, but to no avail. Here are the relevant sections from my service's app.config:

<service name="UploadService">
    <endpoint address="" 
              binding="webHttpBinding" 
              bindingName="StreamedRequestWebBinding"
              contract="UploadService" 
              behaviorConfiguration="webBehavior">
        <identity>
            <dns value="localhost" />
        </identity>
    </endpoint>
    <host>
        <baseAddresses>
            <add baseAddress="http://localhost:8732/UploadService/" />
       </baseAddresses>
    </host>       
</service>

<bindings>
    <webHttpBinding>
        <binding name="StreamedRequestWebBinding" 
                 bypassProxyOnLocal="true"
                 useDefaultWebProxy="false"
                 hostNameComparisonMode="WeakWildcard"
                 sendTimeout="00:05:00"
                 openTimeout="00:05:00"
                 receiveTimeout="00:05:00"
                 maxReceivedMessageSize="2147483647"
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 transferMode="StreamedRequest">
            <readerQuotas maxArrayLength="2147483647"
                          maxStringContentLength="2147483647" />
        </binding>
    </webHttpBinding>
</bindings>

<behaviors>
    <endpointBehaviors>
        <behavior name="webBehavior">
            <webHttp />
        </behavior>
    <endpointBehaviors>
</behaviors>

How do I make my service accept more than 64 kB of streamed post data?

Edit: as shown in the client code above, I am not using service references, rather constructing the HTTP request by hand. (This is because Silverlight service references do not support streams.)

like image 835
Mike Chamberlain Avatar asked Jan 10 '11 02:01

Mike Chamberlain


1 Answers

So I found the problem - bindingName="StreamedRequestWebBinding" should be bindingConfiguration="StreamedRequestWebBinding". With the former, my the binding configuration specified was not being used at all, so maxReceivedMessageSize defaulted to 64kB.

like image 155
Mike Chamberlain Avatar answered Nov 10 '22 16:11

Mike Chamberlain