While reading WCF technical forums, I have come across the following questions a number of times:
- How to download a large file from a WCF Service?
- I am getting an error while transferring a large file from WCF service to client?
- How to send large messages or data from WCF Service to a client?
So, I decided to write a simple WCF Tutorial on this topic with possible approaches to answer the above questions. I'll follow a step by step method to provide a complete solution as follows:
So, we will try to understand the problem that is involved with downloading a large file from a WCF service. For the purpose of implementation, we will create a simple WCF Service that returns a byte array.
- First of all, let's create a WCF service contract
IMyBookService
that returns a Book
.
public interface IMyBookService
{
[OperationContract]
Book DownloadBook();
}
Book DataContract
has multiple members, i.e., Title
, ISBN
, Author
and Data
(a byte array).
[DataContract]
public class Book
{
[DataMember]
public string Title { get; set; }
[DataMember]
public string ISBN { get; set; }
[DataMember]
public string Author { get; set; }
[DataMember]
public byte[] Data { get; set; }
}
- Implementation of
IMyBookService
is as follows:
public class MyBookService : IMyBookService
{
Book IMyBookService.DownloadBook()
{
Book myBook = new Book();
myBook.Title = "WCF RESTful Service";
myBook.ISBN = "178-3-15-146510-0";
myBook.Author = "Imran Abdul Ghani";
myBook.Data = File.ReadAllBytes(@"D:\MyBooks\WCF RESTful Service.doc");
return myBook;
}
}
- Configuration settings for the service is given below:
<services>
<service name="BookService.MyBookService" behaviorConfiguration="serviceBehavior">
<endpoint address=""MyBookService"
Binding = "wsHttpBinding" bindingConfiguration = "wsBindingConfig"
Contract = "BookService.IMyBookService" />
<host>
<add baseAddress="http://localhost:9999" />
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsBindingConfig" messageEncoding="Text" />
</wsHttpBinding>
</bindings>
In order to consume the service, the client side code will be as follows:
BookService.MyBookServiceClient client = new BookService.MyBookServiceClient();
client.Book myBook = client.DownloadBook();
File.WriteAllBytes(@"D:\MyDownloadedBooks\" + myBook.Title, myBook.Data);
When we call the download method of MyBookService
through client code, it will generate the following exception:
"Maximum message size quota for incoming messages (65536) has been exceeded...."
So, we have reached at a point that how a WCF service behaves by default for such scenarios. One thing is obvious from the above error message that Maximum message size for downloading a file in WCF, by default, is around 65K. In order to handle this issue, simply increase the value of two configuration settings:
maxReceivedMessageSize
readerQuotas
So, updated bindingConfiguration
will be as follows:
<bindings>
<wsHttpBinding>
<binding name="wsBindingConfig"
maxReceivedMessageSize="10000000"
messageEncoding="Text">
<readerQuotas maxArrayLength="1000000" />
</binding>
</wsHttpBinding>
</bindings>
Now, if we run the above code, it will work fine and the file will be successfully downloaded. Cheers...
Although we got the answer to questions asked at the start of this WCF Service tutorial, this approach has some disadvantages with respect to performance.
- As we have seen, we are using default
messageEncoding
i.e. "Text
". Text encoding uses base 64 encoding format. Base 64 encoded files are normally larger than the original file size, so further increasing the file size to approximately 30% unnecessarily. - Also there is a cost for encoding at one end and decoding on the other.
In order to do the same, we have a better approach and that is to use MTOM (Message Transmission Optimization Mechanism) message encoding. We just need to replace MTOM in the above binding configuration instead of Text.
<bindings>
<wsHttpBinding>
<binding name="wsBindingConfig"
maxReceivedMessageSize="10000000"
messageEncoding="Mtom">
<readerQuotas maxArrayLength="1000000" />
</binding>
</wsHttpBinding>
</bindings>
Using MTOM message encoding format has advantages listed below:
- It keeps the size of message under control.
- Interoperable because it's based on Open specification.
Hopefully, this simple WCF article will be helpful in answering the above mentioned questions. Further, I am planning to write another Tutorial on "How to upload large data to a WCF Service?" later this month. So, be in touch and enjoy service programming.
Reader of this article might also be interested in: