Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi all!

I used the netcfSvcUtil.exe tool to generate the wcf service the mobile client will use to connect to the server.
The client uses a basicHttpBinding, which is required for WCF on the compact framework. There isn't TransferMode="Streamed". There's only TransferMode="Buffered".

I decided to separate sended/received file.
The chunk's size is 262144.
It works great when I receive file.
code snippet:
DocumentLibraryServiceClient doc = new DocumentLibraryServiceClient();

            string downloadfilename = @"\Program files\Download.txt";
            using (FileStream fs = new FileStream(downloadfilename, FileMode.Create, FileAccess.ReadWrite))
            {
                FileInfo fid = new FileInfo(); fid.FileName = "Download.txt"; fid.OffsetFile = 0;
                FileChunk fcd = new FileChunk(); fcd.FileSize = 1; fid.OffsetFileSpecified = true;
                while (fid.OffsetFile != fcd.FileSize)
                {                    
                    fcd = doc.DownloadDocument(fid);
                    fs.Seek(fid.OffsetFile, SeekOrigin.Begin);
                    fs.Write(fcd.Data, 0, fcd.Data.Length);

                    fid.OffsetFile += fcd.Data.Length;
                }
            }


public static System.ServiceModel.Channels.Binding CreateDefaultBinding()
    {
        System.ServiceModel.Channels.CustomBinding binding = new System.ServiceModel.Channels.CustomBinding();
        binding.Elements.Add(new System.ServiceModel.Channels.TextMessageEncodingBindingElement(System.ServiceModel.Channels.MessageVersion.Soap11, System.Text.Encoding.UTF8));
        System.ServiceModel.Channels.HttpTransportBindingElement http = new System.ServiceModel.Channels.HttpTransportBindingElement();
        http.MaxBufferPoolSize = 300000;
        http.MaxBufferSize = 300000;
        http.MaxReceivedMessageSize = 300000;
        http.TransferMode = System.ServiceModel.TransferMode.Buffered;
        binding.Elements.Add(http);
        return binding;
    }


But when I send file it's failed.
code snippet:
string uploadfilename = @"\Program files\Upload.txt";            
            using (FileStream fs = new FileStream(uploadfilename, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] b = new byte[262144];//If size is 16384 - it works good!
                int byteReads;
                FileInfo fi = new FileInfo(); fi.OffsetFileSpecified = true;
                FileChunk fc = new FileChunk(); fc.OffsetFileSpecified = true;
                fc.FileName = "Upload.txt"; fc.FileSize = (int)fs.Length;
                while ((byteReads = fs.Read(b, 0, b.Length)) > 0)
                {
                    fc.Data=b;                  
                    fi = doc.UploadDocument(fc);
                    fc.OffsetFile += byteReads;
                    if (fi.OffsetFile == fc.FileSize) MessageBox.Show("File sended successfully!");
                }               
            }


I've got message:

The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader.


Unfortunately, XmlDictionaryReaderQuotas doesn't have MaxArrayLength property in Compact Framework...

How to increase length quota?
Please, help me!
Posted

1 solution

In config with standard http or wsHttp bindings, you would usually do this:

XML
<binding name="myBinding">
    <readerquotas maxarraylength="2147483647"></readerquotas> <!-- int32.Max -->
</binding>


In code with a custom binding, you need to add a MessageEncoding element. You've done the transport layer, you need to go up a step, like so (I'm assuming here you'll use binary message encoding which is good for file transfer):

C#
System.ServiceModel.Channels.CustomBinding binding = new System.ServiceModel.Channels.CustomBinding();
        binding.Elements.Add(new System.ServiceModel.Channels.TextMessageEncodingBindingElement(System.ServiceModel.Channels.MessageVersion.Soap11, System.Text.Encoding.UTF8));
        System.ServiceModel.Channels.HttpTransportBindingElement http = new System.ServiceModel.Channels.HttpTransportBindingElement();
        http.MaxBufferPoolSize = 300000;
        http.MaxBufferSize = 300000;
        http.MaxReceivedMessageSize = 300000;
        http.TransferMode = System.ServiceModel.TransferMode.Buffered;
        binding.Elements.Add(http);

        // here, create the message element
        var messageElement = new System.ServiceModel.Channels.BinaryMessageEncodingBindingElement();
        messageElement.ReaderQuotas.MaxArrayLength = Int32.Max; // largest possible value, but you set it as necessary to your situation

        // don't forget to add it to the binding's elements collection
        binding.Elements.Add(messageElement);

        return binding;


The error message stating "This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader" is because underneath the framework is instantiating an XmlReader with the quotas specified in the binding element. Once you add your message encoding element, the XmlReader it then creates will have a larger MaxArrayLength :)

Hope that helps! :)
 
Share this answer
 
v2
Comments
_Ares!!! 26-Apr-11 21:09pm    
Unfortunately, there isn't the BinaryMessageEncodingBindingElement and the messageElement doesn't have ReaderQuotas property :( I work with Compact Framework 3.5
GlobX 26-Apr-11 22:17pm    
Sorry dude, missed that bit... I should read more carefully! I will try to figure out an answer. You could use reflection as a massive hack, but you didn't hear that from me... :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900