 |
|

|
I am really ticked off at M$ for not adding built in decompression support to WCF clients , since this functionality was availably with HTTPSoapProtocol clients through the EnableDecompression property.
Your method will really come in handy with WCF clients using basicHTTPBinding. I hope!
In any case, this is an awesome tip. Thanks!
|
|
|
|

|
Thank you for your comments.
I believe decompression is allowed on .NET 4.0, but I'm not sure at this moment.
|
|
|
|

|
Paulo Morgado wrote: I believe decompression is allowed on .NET 4.0, but I'm not sure at this moment.
It is, but for those of us who are no longer using asmx services, and are not on 4.0 yet, its a case of "jam yesterday and jam tomorrow, but never jam today".
|
|
|
|

|
I understand your pain. My main work is on a codebase partly in .NET 1.1 and partly on .NET 2.0 that targets .NET 2.0 (no SPs).
|
|
|
|

|
What I have to do to use Your CompressibleHttpWebRequest an CompressibleHttpWebResponse?
Usage of cerator is explained but I cant figure out how to use the others.
Im trying to combine Your solution with WsHttpBinding to decompress gzipped message.
Thanks for any help
g
modified on Thursday, August 26, 2010 8:08 AM
|
|
|
|

|
"cerator"???
What version of the .NET framework are you using?
What exactly are you having trouble with?
|
|
|
|

|
creator was for CompressibleHttpRequestCreator.
.net 3.5
im having trouble with using HhttpRequest and Response since im operation on channel from ChannelFactory.
If i replace http prefix (in config) to use CompressibleHttpRequestCreator, it is used, but i believe there is no way to inject Yours Compressibles to channel communication. At least i dont know how :(
|
|
|
|

|
I've never used this with WCF, but I blieve that WCF uses HttpWebRequest/HttpWebResponse.
Bare in mind that this is a technic to inform the server that the client is capable of handling compressed responses.
Have you used Fiddler or some other tool to see if the Accept-Encoding HTTP header is being sent to the server?
|
|
|
|

|
My requests are accepting encoding. I receive compressed message and there is the problem I cant find point to decompress it to read to allow read soap message.
In WCF I can call service with HttpWebRequest but manually constructed message is not clean solution for me. Id rather call it using channel and intercept reply to modify it. Maybe it cant be mixed that way.. :/
Btw thanks for support
Greg
|
|
|
|

|
I can see that the Accept-Encoding HTTP header.
Is the server sending the Content-Encoding header? (I need to setup a server with compression to test this)
|
|
|
|

|
Yes, message is compressed. I am using IIS server dynamic compression.
|
|
|
|

|
This is exactly what we needed. This way, we dont have to change the dozens of web services we have already authored, AND we can compress secured communications (e.g. wsHttpBinding) which we couldnt do with the gzip sample from MS, AND we can un-gzip it with fiddler. Thanks!
|
|
|
|
|

|
Hi,
I have tried the code and it seemed to be working, loading all the right classes etc. Then I tried a test with a webservice I have for copying files from a to b. Hoping to see how good the compression was working.
So I copied 685 files from between 300kb and 1.8 mb in size. For a total of 455mb. Without compression within intranet it takes just under a minute. With the compression it takes over 8 minutes and uses 1.2 gb bandwidth....
What an earth am I doing wrong...! ??
|
|
|
|

|
That's odd.
Have you tried to use Fiddler (or any other tool) to see what's going on?
|
|
|
|
|

|
Thanks for the reference.
|
|
|
|

|
When I am running my site with your adjustments, it does not seem to use the CompressibleHttpRequestCreator object to create the web request.
The unusual behaviour extends to the fact, if i break the code within visual studio and then use the immediate window to manually create a webrequest, then it actually does run and use the appropriate class.
Any assistance would be appreciated.
Thanks
Matt Thompson
|
|
|
|

|
As far as I know with .Net 2.0 you just have to add this line, where "request" is a HttpWebRequest object:
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
Is there any other reason I might not have seen to use your solution?
Kind regards, Björn
|
|
|
|

|
None, other than the fact that I missed it completely. I already submeted the correction.
Thanks a lot Björn.
|
|
|
|

|
Thanks for the article!
But, compiling the code, I've got two warnings:
1. CompressibleHttpWebResponse.cs(20,10): warning CS0618: 'System.Net.HttpWebResponse.HttpWebResponse(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' is obsolete: 'Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202'
2. CompressibleHttpWebRequest.cs(27,28): warning CS0618: 'System.Net.HttpWebRequest.HttpWebRequest(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' is obsolete: 'Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202'
Of course, we can just ignore this, but is there a good way to fix it?
|
|
|
|

|
Thanks nzeemin.
Unfortunatelly this was the only way I found to implement this.
You can add a #pragma directive to ignore this warning in this case.
|
|
|
|
|

|
I'm sorry but I'm failing to understand your point.
My article is about client-side and your links point to the server-side of the problem. They are not the same thing but one needs the other.
|
|
|
|

|
Greetings Paulo,
I've implemented your code and everything seems to work correctly except the ContentEncoding property from the HttpWebResponse object is returning "", not 'gzip', or 'deflate', which of course is a major problem.
This app is a Windows Forms program using Web Services and .NET 2.0. I've dropped in your code and modified the app.config in between the configuration tags as:
Fiddler is showing 'Accept-Encoding: gzip, deflate' so it seems the encoding request is being sent to the server but it's not responding as needed. Is there anything I need/can to do to the server to get it to compress properly
Thank you,
Ed
|
|
|
|

|
Hi Ed,
The way the protocol works is by the client announcing to the server what encondings it accepts. If the server is capable of using one of them, it encondes the response and adds the respective Content-Encoding HTTP header.
IIS 6.0 is capable of handling this, but lower version aren't.
For IIS 5.x, you can add an HTTP module to your ASP.NET application to handle compression. Here is an example of one implementation: http://www.blowery.org/code/HttpCompressionModule.html.
You can, also, use Fiddler to emulate server side compression.
|
|
|
|

|
Hi Paulo,
Well, we've finally found the time to move this app to IIS 6.0 and that's when I found that compression still wasn't working.
I've enabled HTTP Compression in Web Site Properties from IIS Manager for IIS 6.0 and can't find any other properties to set.
This app uses XML data objects (soap) passed from a Winforms client to a webservice dll now on Server 2003. Do you know if there is anything further I can do to get it working in our environment? We appreciate your article and consideration.
Thank you,
Ed
|
|
|
|

|
Have you checked with Fiddler if the rigth HTTP headers are being sent?
You should be aware that this is a server side compression only protocol and, ASMX being a dynanlic content needs compression explicitly enabled on IIS6.
If you need to send compressed data to your web server, you need to code your web service to handle that (or your WCF binding).
There are also issues with this on .NET 1.1. I wonder if they affect .NET 2.0.
|
|
|
|

|
Of course you're right about the dynamic content in IIS 6.0. I followed the instructions here:
http://www.wwwcoder.com/main/parentid/170/site/3669/68/default.aspx
and everything is working fine. Thank you Paulo.
|
|
|
|

|
can't compile the code including the given classes since I miss the System.Runtime.Serialization reference.
and it's no where to be found.
any suggestions?...
thanks
|
|
|
|

|
You can find it int he framework directory (usually, C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727).
I don't believe my code needs it, though.
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|

|
well, I got to the problem: I'm developing for a device, and the Compact Framework does not contain the System.Runtime.Serialization library, so I can't use your methods.
is there ant way of using another serialization method maybe to get the sae result with CF?
and yet another question - does your compression work on IIS 5.1? is it IIS dependant? cause for now I'm using the IIS 6.0 compression (gzip), but I need to be able to do the same via IIS 5.1, which does not support http compression.
Thanks
|
|
|
|

|
Well, I've never developed for the Compact Framework, so I don't have a feeling for what's there and what's not.
This classes I've developed are not server dependent and can be used to replace HttpWebRequest and HttpWebResponse for the desired addresses just by adding some elements to the application's configuration file.
In your case, you'll need to develop a new set of classes (probably derived from WebRequest/WebResponse instead of HttpWebRequest/HttpWebResponse) and bind your applications to them. You'll find several examples of that around the internet.
The way this works is announcing to the server that the client is accepting GZIP and DEFLATE compression methods and it can send a response using that compression methods.
For IIS 5.x, you can add an HTTP module to your ASP.NET application to handle compression. Here is an example of one implementation: http://www.blowery.org/code/HttpCompressionModule.html.
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|

|
I implement your solution and I can not now handle web specific exception.
when I implement your solution the code crash with The remote server returned an error: (500) Internal Server Error, in method base.GetResponse() in this code in CompressibleHttpReques.
can somebody help?
Petr M.
public override WebResponse GetResponse()
{
BeforeGetResponse();
return AfterGetResponse(base.GetResponse() as ISerializable);
}
|
|
|
|

|
If the server returned an error 500 there should be an exception thrown.
Am I missing something?
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|

|
public override WebResponse GetResponse()
{
try
{
BeforeGetResponse();
return AfterGetResponse(base.GetResponse() as ISerializable);
} catch (WebException webEx)
{
throw new WebException(webEx.Message, webEx.InnerException, webEx.Status, AfterGetResponse(webEx.Response));
}
}
...
public override WebResponse EndGetResponse(IAsyncResult asyncResult)
{
try
{
return AfterGetResponse(base.EndGetResponse(asyncResult) as ISerializable);
} catch (WebException webEx)
{
throw new WebException(webEx.Message, webEx.InnerException, webEx.Status, AfterGetResponse(webEx.Response));
}
}
Modifying the above methods in CompressibleHttpWebRequest allows for SOAP exceptions to be read correctly. This is because when an HTTP error is thrown, the WebException.Response property contains the error stream, which needs to be turned into the CompressibleHttpWebResponse stream for any compressed stream to be read. SOAP exceptions / reading HTTP error streams will now work correctly.
|
|
|
|
|

|
I cant get it working :/
I have compiled it into a dll and put it in ~/Bin and I had set up the web.config like described above but nothing happens, all works as like as without this (checked with ethereal and fiddler)...
But the Type seems to be correctly; if i execute type.gettype with it out of my web, I get the correct type out of the .dll.
Are there some things to know, such as needed security privileges?
Is it possible to add this libary from source-side (global.asax)?
Thanks for all
Sorry for my english
|
|
|
|

|
Using Ethereal and Fiddler, did you check if the Accept-Encoding is being sent?
You could set breakpoints in CompressibleHttpRequestCreator.Create, CompressibleHttpWebRequest.BeforeGetResponse, CompressibleHttpWebRequest.AfterGetResponse and CompressibleHttpWebResponse.GetResponseStream to see what's going on.
To make sure the right classes are instantiated, you can, also, create the WebRequest instance like this:
IWebRequestCreate webRequestCreate = new CompressibleHttpRequestCreator();
WebRequest webRequest = webRequestCreate.Create(uri);
WebResponse webResponse = webRequest.GetResponse();
You can register a IWebRequestCreate descendant for a spceified prefix in code using WebRequest.RegisterPrefix, but you can't override the definitions for HTTP and HTTPS. And you would end up with your code tightly coupled with these classes. This is the sort of thing you want plugguble.
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|
|

|
If you added the code to your sources (no need to convert to vb with 2.0) you can step into the code with this:
IWebRequestCreate webRequestCreate = new CompressibleHttpRequestCreator();
WebRequest webRequest = webRequestCreate.Create(uri);
WebResponse webResponse = webRequest.GetResponse();
Fiddler, in the Rules menu has a Simulate GZIP Compression. Have you tried it.
If the Accept-Encoding header are being sent, it's because CompressibleHttpWebRequest.BeforeGetResponse is being executed.
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|
|

|
This code is only for outgoing requests and the server needs to understand the Accept-Encoding header.
If you are looking for the same thing for the server side (handling incoming requests) you can try this HTTP Compression Module. With this, you can set breakpoint on the server side code and check what's going on.
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|

|
ok, it seems I have mistranslated the description...
But many thanks for your support
|
|
|
|

|
I tried this code into my web application - web dev express, nothing change.
I added following code into web.config and i put the files(downloaded) into the app_code -> HttpCompression directory. But i didn't see any difference in the response header.
<!--
-->
Even if i change the Pajocomo.Net.CompressibleHttpRequestCreator into something like abc in the web.config file it doesn't affect and doesn't get any error in the web application.
Whats wrong? I didn't change the downloaded source files.
Please help me.
Regards
R.Arockiapathinathan
|
|
|
|

|
Have you set breakpoints to see if the code is being executed?
What is the running type of the WebRequest instance returned by WebRequest.Create?
Aren't you missing the assembly name in your config?
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|

|
Thanks for reply.
<configuration>
<system.net>
<webRequestModules>
<remove prefix="http:"/>
<add prefix="http:"
type="Pajocomo.Net.CompressibleHttpRequestCreator" />
</webRequestModules>
</system.net>
</configuration>
This is my configuration in web.config file. I am using web dev express. So i couldn't compile to get assembly. Thats why, i put the source code files under App_Code directory.
I set breakpoint in CompressibleHttpRequestCreator.cs file's WebRequest IWebRequestCreate.Create(Uri uri) , but cursor didn't come there.
All 5 Source files are under App_Code->HttpCompression directory.
I didn't find any related detailed articles (about this webrequestmodules) from msdn as well as google search ...
So related links are also welcome ....
Thanks in advance.
Regards
R.Arockiapathinathan
|
|
|
|

|
You should, at least be getting an exception.
Try something like this:
<configuration>
<system.net>
<webRequestModules>
<remove prefix="http:"/>
<add prefix="http:"
type="Pajocomo.Net.CompressibleHttpRequestCreator, App_Code" />
</webRequestModules>
</system.net>
</configuration>
The webRequestModules config section is very hard to find either in 1.1 or 2.0 documentation. And, to be in sync with MSDN, the same happens in my article. Just lok for the webRequestModules in the text and you will find that that's a link to the documentation.
Paulo Morgado
Portugal - Europe's West Coast
|
|
|
|

|
No improvement, Still same thing ......
I couldn't understand the webrequestmodule element.
Can you send me the sample project(full executable version)?
May be, that will help to understand.
my email id - rsarockiam@gmail.com
I appreciate your help to solve this problem.
Thanks in Advance
Regards
R.Arockiapathinathan
|
|
|
|
 |