The factory pattern of creating WebRequest instances

The WebRequest class uses instances of classes that implement the IWebRequestCreate interface and are registered in the webRequestModules section in the configuration files. The Create method (called by both CreateDefault and Create) returns an initialized instance of a WebRequest descendent class capable of performing a standard request/response transaction for the protocol without needing any protocol-specific fields modified.

Because we can control the WebRequest factory using the configuration files, we can change the behavior of already built applications (our applications, or even the .NET Framework) to request and handle HTTP compression without changing them.

The WebRequest descendent instances will be responsible to create the WebResponse descendent instance that will handle the response from the web server.

The code

As shown before, to add HTTP compression to our applications, we just have to build three classes:

Fortunately, HttpWebRequest and HttpWebResponse are not sealed (NotInheritable in VB.NET). Unfortunately, these classes don't have any public constructor, and the only protected constructor each one has is the one required by the implementation of the ISerializable interface. Due to this drawback, reflection must be used.

CompressibleHttpRequestCreator

As mentioned before, the only way to create an instance of a HttpWebRequest derived class, is by deserialization. To accomplish this, an instance of HttpWebRequest will be created, serialized, and deserialized into an instance of CompressibleHttpWebRequest.

CompressibleHttpWebRequest

This class will handle the setup of the HTTP request and the creation of the HttpWebResponse derived instance to handle the response.

As with CompressibleHttpWebRequest, when creating the HttpWebResponse, an instance of HttpWebResponse will be created, serialized, and deserialized into an instance of CompressibleHttpWebResponse.

To specify what types of compression will be accepted in the response, the AcceptEncodings will be used. Its value will, also, be used to set the accept-encoding HTTP header in the request (in the BeginGetResponse). The possible values for AcceptEncodings are:

Identity - The default (identity) encoding; the use of no transformation whatsoever.

GZip - An encoding format produced by the file compression program "gzip" (GNU zip) as described in RFC 1952 [25]. This format is a Lempel-Ziv coding (LZ77) with a 32 bit CRC.

Deflate - The "zlib" format defined in RFC 1950 [31] in combination with the "deflate" compression mechanism described in RFC 1951 [29].

CompressibleHttpWebResponse

This is the easiest one. All that's needed is to handle the response stream accordingly to the content-encoding HTTP response header. Unfortunately, the .NET Framework 1.1 base classes don't provide any class for handling Deflate and GZip streams. For that, the SharpZipLib will be used.

Comments and Discussions

I am new in webservice and c#. Please mention how to use these classes in terms of Webrequest/Webresponse compression. Please make an example in which Creator, Request and Response is used. Also specify the exact paramenter which can be used in these classes. I am using asp.net 1.1.

Here is the code I used to test the compression. Both passes return the same result, but the response from the server on the second test is about 90% smaller. Also, when stepping through the code in the first pass, ContentEncoding is the empty string. In the second pass, it is "gzip".

Hey -- thanks for responding. I'm not sure what you're talking about with the "static content". The instructions in the link I referred to sets IIS6 to compress both "Application" files and "Static" files.

Fiddler doesn't report calls to web services from ASP.NET 1.1 (although it does from 2.0 & above), so that was not much use.

I was able to find a machine with the old Visual Studio.NET, and determined that the header was getting added, but then it was getting removed somehow (still don't know how) before being sent.

I added the header in the Web Service Proxy as follows, and now I'm getting compression back from the web service. Everything's working great now.

Thank you for the great article, but ... hm, there is something wrong I've just recode it on VB and add the stuffs in the webconfig, but the compression doesnt work. Also put a breakpoint in CompressibleHttpRequestCreator's Create function and it never gets into it. Any ideas ? Here is my VB interpretation.