JSprang
JSprang

Reputation: 12909

How to transfer large amount of data using WCF?

We are currently trying to move large amounts of data to a Silverlight 3 client using WCF with PollingDuplex. I have read about the MultiplerMessagesPerPoll in Silverlight 4 and it appears to be quite a bit faster. Are there any examples out there for me to reference (using MultipleMessagesPerPoll)? Or maybe some good references on using Net.TCP? Maybe I should be taking a completely different approach? Any ideas or suggestions would be greatly appreciated.

Thanks!

Upvotes: 4

Views: 4708

Answers (3)

Austin Salonen
Austin Salonen

Reputation: 50215

I'm basing this on your answer and its emphasis on the size of the data you're transferring. If you're keeping the blocks of data transferred under 4GB, you can make use of the GZipStream class in the System.IO.Compression namespace. In my experience using it with plain text, it reduced the data stream to about 17-20% of its original size.

Upvotes: 1

JSprang
JSprang

Reputation: 12909

I implemented the suggested solution above. After implementation, I found this link:

http://msdn.microsoft.com/en-us/library/ms752244.aspx

I then implemented the Binary writer, as shown below.

Service Method:

[OperationContract]
    public Stream GetAllLocationsDataStream(string customerId)
    {
        Stream stream = new MemoryStream();
        try
        {
            Customer customer = ServiceEquipmentManager.GetCustomerAllLocations(customerId);
            DataContractSerializer serializer = new DataContractSerializer(typeof(Customer));
            XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream);
            serializer.WriteObject(binaryDictionaryWriter, customer);
            binaryDictionaryWriter.Flush();
        }
        catch (Exception ex)
        {
            string timestamp;
            ExceptionHelper.HandleExceptionWrapper(ex, "Log Only", out timestamp);
        }

        stream.Position = 0;
        return stream;
    }

Client-side Completed Event:

XmlDictionaryReader binaryDictionaryReader = XmlDictionaryReader.CreateBinaryReader(new MemoryStream(e.Argument as byte[]), XmlDictionaryReaderQuotas.Max);

        Customer customer = serializer.ReadObject(binaryDictionaryReader) as Customer;

I checked the difference of my object as shown in the link above, my results are shown below:


Text = 68,866,216 bytes


Binary = 49,207,475 bytes (28.5% less than Text)

Upvotes: 2

KodeKreachor
KodeKreachor

Reputation: 8882

Streaming serialized response chunks works well:

Your WCF binding configuration would resemble the following:

<binding name="myCustomBinding">
   <binaryMessageEncoding />
   <httpTransport transferMode="StreamedResponse" 
                  maxBufferSize="2147483647" 
                  maxBufferPoolSize="2147483647" 
                  maxReceivedMessageSize="2147483647" />
</binding>

Your Service method would look something like:

[OperationContract]
public Stream GetDataStream(string objectId)
{
   Stream stream = new MemoryStream();

   MyObject obj = Manager.GetObject(objectId);

   DataContractSerializer serilizer = new DataContractSerializer(typeof(MyObject));

   serilizer.WriteObject(stream, obj);

   stream.Position = 0;

   return stream;
}

And your client-side completed method would do something like:

static void client_GetDataStreamCompleted(object sender, GetDataStreamCompletedEventArgs e)
{
   if (e.Error == null)
   {
      DataContractSerializer serializer = new DataContractSerializer(typeof(MyObject));

      MyObject obj = serializer.ReadObject(new MemoryStream(e.Result)) as MyObject;
   }
}

Upvotes: 2

Related Questions