Cry about...
MS-Windows Troubleshooting


ProtocolException: The remote server returned an unexpected response: (400) Bad Request.


Symptom:

When making a request to a web-service the following System.ServiceModel.ProtocolException is throw:

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

in my case I was passing a large byte array to the web-service.

Cause:

The "400 Bad Request" response is generated by the remote server hosting the web-service, and is caused simply because the request being sent to the remote server is too large. The default settings restrict the largest message to 65536 bytes, and the total message size is larger than this (or the current size setting).

Note: There may be other causes which I have not yet encountered.

Possible Remedies:

  • Reduce the size of the message being sent, i.e. reduce the amount of data being sent. For example if the data includes an image then can the quality (and thus size) of the image be reduced? (It is acknowledged that this is often not practical.)
  • Consider streaming data to the web-service instead of loading it directly.
  • The maximum receive message size at the remote server needs to be changed. This is only an option is you are responsible for the web-service on the remote web-server.

    On the remote server edit the web.config file. To set the maximum receive message size first (i.) create a new binding which takes the new receive message size and then (ii.) associated that binding with the web-service.

    Step 1. Create a new binding with the new receive message size

    In the web.config file add a new binding, and set the maxReceivedMessageSize for that binding to the desired value.

    So if you wanted to be able to receive messages up to say 1MB (1,048,576 bytes) then you could add a binding similar to the following:

    <configuation>
     .
     .
     <system.serviceModel>
      .
      .
      <bindings>
       <basicHttpBinding>
        <binding name="Binding1" maxReceivedMessageSize="1048576"/>
       </basicHttpBinding>
      </bindings>
      .
      .
     </system.serviceModel>
    </configuration>

    The name "Binding1" in the above is not significant, but it must be unique. So if you have multiple different bindings then each must have a unique name. A descriptive name might be better than the name I have used above. The maxReceivedMessageSize value is specified in bytes.

    Step 2. Associate that binding with the web-service

    In the web.config file add a service record, such as:

    <configuation>
     .
     .
     <system.serviceModel>
      .
      .
      <services>
       <service name="MyService">
        <endpoint address="" binding="basicHttpBinding"
         bindingConfiguration="Binding1"
         contract="IMyService"/>
       </service>

      </services>
      .
      .
     </system.serviceModel>
    </configuration>

    The service name must be the fully qualified name of the service. If you are not sure what this is then look in the corresponding .svc file and it should be the same as the name given there.

    The bindingConfiguration should be set to the same name used when creating the binding with the larger maxReceiveBufferSize.

    The contract should be the fully qualified name of the service contract class or interface.

    Be aware that allowing larger requests does make the server more prone to possible denial of service requests. So consider carefully how large a request you will allow, and consider whether there might be a safer alternative.


These notes have been tested within Microsoft Visual Studio .NET 2010 (.NET 4), and may apply to other versions as well.



About the author: is a dedicated software developer and webmaster. For his day job he develops websites and desktop applications as well as providing IT services. He moonlights as a technical author and consultant.