Friday, April 29, 2011

Transfer large messages in WCF - Part 1

Pre Requisites
                Readers must have knowledge in creating basic WCF service and must know how to host and consume a service.
Default max received message size in WCF is 65kb, so when we try to send messages more than 65kb, WCF will give errors. Let us create a basic service which will pass a message more than 65 k and see what happens and figure out what are different ways to handle large messages in WCF.

1. Create a service contract that takes byte[] as input as shown below:
public interface IService1
   void UploadFile(byte[] data);
2.  Implement Iservice1 which will write byte[] into file on a server
public class Service1 : IService1
  public void UploadFile(byte[] data)
    Random x = new Random();
    string fileName = string.Format(@"Test{0}.mp3", x.Next().ToString());        

3.  The app.config file for the hosting environment is given below:
      <service name="FileUpload.Service1">
            <add baseAddress = "http://vital-pc:7998/FileUpload/Service1/" />
        <endpoint address ="" binding="basicHttpBinding" contract="FileUpload.IService1">
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False" />

4.  Now consume this service in a client. Here we will convert a mp3 file into byte[] which is more than 65 kb and send it to service
FileStream fs = new FileStream(@"Test.mp3", FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];  
ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client();

5.  Make sure you enable the trace at service so that we can see the detailed error messages

6.  Make sure service is running and execute the client .

7.  As expected we got an error (look into trace at service) which says “The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.”. So we have to increase MaxReceivedMessageSize as below
  <binding name="largeObjects" maxReceivedMessageSize="6500000" ></binding>
a.  You can set maxReceivedMessageSize upto 2GB (2147483647, i.e. Int32.MaxValue)

b.  Interesting point over here is when we get above error do we need to increase maxReceivedMessageSize at service or client?
                 i. If we change maxReceivedMessageSize value at a service, it refers to the maximum message size that the service can receive. We need to change this value when we get large data from client
                 ii. If we change maxReceivedMessageSize value at client, it refers to the maximum message size that the client can receive. We need to change this value when we get large data from service
Since the data we are sending from the client exceeds the maximum permissible limit on the service, it is clear that for our problem we need to increase the maximum message size at service
             c.  maxReceivedMessageSize is a local behavior setting  i.e if you do some changes to maxReceivedMessageSize value at service and try to refresh service reference at client this value will not be updated, it will be always default value(65536) at client. This make sense with explanation in point b that explains different meanings for this property at client and service .

We have seen how we can transfer large data in WCF. But when we are working with large data, the first things that come into our mind  are memory and processing overhead. These things can be addressed using

Let us go into details of each one with examples in Part 2 and Part 3.

Hope this helps