Chrome failing to decompress gzip, content length
My Silverlight 4 app downloads quite a bit of data from the server through a WCF service, so I implemented gzip compression using the technique described here: http://forums.infragistics.com/blogs/anton_staykov/archive/2010/08/24/silverlight-wcf-service-compression-azure.aspx
In short, I extended the WCF gzip encoder sample ( http://msdn.microsoft.com/en-us/library/ms751458.aspx ) to work with Silverlight. The server compresses the WCF responses with gzip, and on the client side, the browser HTTP stack decompresses the response automatically before it gets to Silverlight. All is well, and the compression works very nicely in IE.
Testing the same thing in Chrome, however, leads to this..
System.Xml.XmlException: The input source is not correctly formatted.
at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
at System.Xml.XmlBufferReader.ReadValue(XmlBinaryNodeType nodeType, ValueHandle value)
at System.Xml.XmlBinaryReader.ReadNode()
at System.Xml.XmlBinaryReader.Read()
at System.Xml.XmlBaseReader.ReadEndElement()
at System.ServiceModel.Channels.Message.ReadFromBodyContentsToEnd(XmlDictionaryReader reader, EnvelopeVersion en开发者_如何学GovelopeVersion)
at System.ServiceModel.Channels.Message.ReadFromBodyContentsToEnd(XmlDictionaryReader reader)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeReply(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object[] args, IAsyncResult result)
at DataAccess.Model.Silverlight4.DataAccess.RealTimeDataService.RealTimeDataServiceClient.RealTimeDataServiceClientChannel.EndGetNowTime(IAsyncResult result)
at DataAccess.Model.Silverlight4.DataAccess.RealTimeDataService.RealTimeDataServiceClient.DataAccess.Model.Silverlight4.DataAccess.RealTimeDataService.RealTimeDataService.EndGetNowTime(IAsyncResult result)
at DataAccess.Model.Silverlight4.DataAccess.RealTimeDataService.RealTimeDataServiceClient.OnEndGetNowTime(IAsyncResult result)
at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)
I've checked out the requests + responses from both browsers in Fiddler, and they are very nearly identical, with one crucial difference -- Content-Length for the Response is set incorrectly for Chrome. I'm sure this is why the XML SOAP is failing to parse.. Chrome is only decompressing part of the content due to the incorrect content length. What gives? Why would my WCF service send back the wrong Content Length for Chrome but not IE?? I change nothing but the browser - code is identical, and the response bodies are identical (Fiddler can decompress both fine). Anyone have a clue why this is happening?
Fiddler:
~~ Internet Explorer 9 ~~
Request
POST http://127.0.0.1:84/services/RealTimeDataService.svc/binary HTTP/1.1
Accept: */*
Referer: http://127.0.0.1:84/ClientBin/Silverlight4.View.xap
Accept-Language: en-US
Content-Length: 207
Content-Type: application/soap+msbin1
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host: 127.0.0.1:84
Connection: Keep-Alive
Pragma: no-cache
Response
HTTP/1.1 200 OK
Cache-Control: private,no-cache
Pragma: no-cache
Content-Length: 512
Content-Type: application/soap+msbin1
Content-Encoding: gzip
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 08 Jul 2011 16:18:09 GMT
~~ Chrome ~~
Request
POST http://127.0.0.1:84/services/RealTimeDataService.svc/binary HTTP/1.1
Host: 127.0.0.1:84
Connection: keep-alive
Referer: http://127.0.0.1:84/ClientBin/Silverlight4.View.xap
Content-Length: 207
Origin: http://127.0.0.1:84
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30
content-type: application/soap+msbin1
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Response
HTTP/1.1 200 OK
Cache-Control: private,no-cache
Pragma: no-cache
Content-Length: 149
Content-Type: application/soap+msbin1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 08 Jul 2011 16:05:43 GMT
Content-Encoding: gzip
I ended up implementing a workaround to compress the WCF service response and decompress it on the Silverlight library. I used SharpZipLib:
- For the web project: http://sharpdevelop.net/OpenSource/SharpZipLib/
- Silverlight version: http://slsharpziplib.codeplex.com/
In my WCF service, I have both compressed and uncompressed methods.. the compressed methods return byte[] which gets decoded on the Silverlight side. I expose the uncompressed methods, which return the raw objects, because I need the classes of these objects to be exposed to the client side. (if anyone has a better idea of how to do this, I'd love to hear it)
Make you don't set the content-encoding HTTP header for these responses, as they are handled by the SL client app, not by the browser.
I was never able to figure out why Chrome wouldn't decompress my WCF response automatically, but this workaround achieves the same result.
精彩评论