It took me several hours to sort out a problem when sending large messages to a WCF web service, looking for information at various websites. So I thought I’d summarise everything you need to do in one blog post.
We were getting errors such as “Bad Request” (HTTP Status 400) and .NET exceptions such as “System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly. System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly”.
The fixes are all in the web.config
First configure the HTTP Runtime to accept large messages. Note – this is a denial of service risk. Our services are internal so I didn’t need to worry about this.
<system.web>
<httpRuntime maxRequestLength="2097151" />
</system.web>
The rest of the configuration changes are in ServiceModel section. 2147483647 is the maximum for many values (the config items are Int32).
The config below will allow you to send a a large message. A large message that contains lots of objects (hence the maxItemsInObjectGraph) is streamed (transferMode=”Streamed”) in 0.5MB chunks (maxBufferSize=”524288″).The readerQuotas section allows large messages to be deserialized from XML into the service type.
<system.serviceModel>
<services>
<service behaviorConfiguration="IncreasedItemsInObjectGraph"
name="ServiceName">
<endpoint address="" binding="basicHttpBinding" contract="ServiceName.IServiceContract"
bindingConfiguration="BasicHttpBinding_IncreasedMessageSize_Buffered" />
</service>
</services>
<behaviors>
<servicebehaviors>
<behavior name="IncreasedItemsInObjectGraph">
<servicemetadata httpGetEnabled="true" />
<servicedebug includeExceptionDetailInFaults="true" />
<datacontractserializer maxItemsInObjectGraph="2147483647" />
</behavior>
</servicebehaviors>
</behaviors>
<bindings>
<basichttpbinding>
<binding name="BasicHttpBinding_IncreasedMessageSize_Buffered"
maxBufferSize="524288" maxReceivedMessageSize="2147483647"
closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:05:00"
sendTimeout="00:05:00" transferMode="Streamed">
<readerquotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basichttpbinding>
</bindings>
</system.serviceModel>
The client also needs similar settings:
<system.serviceModel>
<bindings>
<basichttpbinding>
<binding name="BasicHttpBinding_IncreasedMessageSize_Buffered" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:05:00" sendTimeout="00:05:00" transferMode="Streamed" maxBufferSize="524288" maxReceivedMessageSize="2147483647">
<readerquotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basichttpbinding>
</bindings>
<behaviors>
<endpointbehaviors>
<behavior name="MoreItemsInObjectGraph">
<datacontractserializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointbehaviors>
</behaviors>
<client>
<endpoint address="http://localhost:409/Service.svc" binding="basicHttpBinding" contract="Service.IServiceContract" bindingConfiguration="BasicHttpBinding_IncreasedMessageSize_Buffered" behaviorConfiguration="MoreItemsInObjectGraph"/>
</client>
</system.serviceModel>