****Just a forewarning that this is an interim step I took to move large messages. In my next post I will talk about streaming data via WCF which works a lot better for the scenario described here*****
For one of my projects we are moving a large file to our service via WCF. By default WCF only allows small messages and arrays to be processed but in my case I am moving a 50-70Mb byte array around. There are a few things you will need to do to get large messages to move around.
The first thing you will probably notice is that when trying to send a large file the connection will just close or return some strange error. This is due to the fact that either the message will timeout or exceed the maxReceivedMessageSize for the binding. This can be modified by adding a binding configuration that sets the send/receive timeouts and the message size.
<
bindings>
<wsHttpBinding>
<binding name="FileTransferBinding"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
maxReceivedMessageSize="73400320" > <!--70MB-->
<readerQuotas maxArrayLength="73400320" />
</binding>
</wsHttpBinding>
</bindings>
WCF also has default limits on the maximum size of an array so I set the maxArrayLength option on the binding to be quite large.
Next all you have to do is set the endpoints binding configuration to be the configuration we just created:
<
endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="FileTransferBinding"
contract="MyProj.IService" />
Now one thing that I would recommend would be to use a binary binding like netTCP instead of a HTTP based binding for a case like this. Unfortunately if you are hosting your service in IIS6 you can only use HTTP based bindings (in IIS7 you can use TCP based bindings in addition to HTTP).
Also if you are hosting your service in IIS you will need to adjust the httpRuntime to allow large files as well. This can be done in the <system.web> section like so: <httpRuntime maxRequestLength="73400" />
For the sake of completeness here is my completed <system.serviceModel> section:
<system.serviceModel>
<services>
<service name="MyApp.Service.FileProcessor"
behaviorConfiguration="MyApp.Service.FileProcessorBehavior">
<
endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="FileTransferServicesBinding"
contract="MyApp.Service.IFileProcessor" />
<
endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</
service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyApp.Service.FileProcessorBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="FileTransferServicesBinding"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
maxReceivedMessageSize="73400320" >
<readerQuotas maxArrayLength="73400320" />
</binding>
</wsHttpBinding>
</bindings>
</
system.serviceModel>
Now as with everything there is more than one way to toss a cat off a bridge. One thing to add to this would be compression to shrink the data being transferred (if the data you are transferring compresses well at least).
WCF has support for streaming data instead of our current buffer approach. Our services code will not kick in until we have received all of the data. If we used a stream approach we could start processing data as it arrives.