Flow Group SASFlow Group
L'erp des Processus Relationnels
Systeme d'Information – Audit Industriel
> Home > Expertise & Knowledge > Technical Articles

Articles


How to use WebServices with the Compact Framework
on PocketPC using HTTP/1.1 Compression

lire la version francophone Version française

Generalities
Implementing ZHttpWebRequest
Implementing ZHttpWebResponse
Registering the zhttp protocol
Changing the WebService's Uri
Configuring IIS 5.0 Server to compress aspx and asmx files
Some useful links...
Revision history...

In his tutorial Retrieving Data from Web Services using Standard HTTP 1.1 Compression, Jacek Chmiel explains how to override the methods GetWebRequest and GetWebResponse .NET Web Service's proxy class to request the server data compression and uncompress them before the SOAP envelop is parsed.

Though this approach is interresting, it is unapplicable to the PocketPC because the Compact Framework does not allow the overriding of these methods. But, we realized that it is possible to define a new protocol, zhttp for instance, that uses WebRequest and WebResponse derived objects designed for compression.

And this approach works with the PocketPC!

WarningThis article has been written with the Beta of the Compact Framework.
  • To get the binaries for the zhttp version compatible with the Final Beta, click here.
  • To get the source files that uses the latest version of SharpZipLib, instead of the prior version NZipLib, click here.
    The implementation of ZHttpWebRequest of this version also override the WebRequest.Timeout property and delegate the call to the underlying HttpWebRequest. Not doing this make any call to the Timeout property throw a NotSupportedException.

Generalities

Apparently, the transfert sequence from a SOAP call is :

  • create an HTTP request through Webrequest.Create with the http protocol;
  • prepare the request to send the SOAP envelop;
  • wait for the response ;
  • read the response stream to interpret the results in the SOAP envelop.

Without changing anything to the WebServices and SOAP objects, both client side and server side, the code we developped create the following sequence :

  • register the zhttp protocol;
  • create an HTTP request through WebRequest.Create with the http protocol ;
  • create the internal HTTP request through WebRequest.Create, without the "z"
  • add the "Accept-Encoding: gzip, deflate" header;
  • prepare the request to send the SOAP envelop;
  • wait for the response ;
  • waith for the internal HttpWebrequest response;
  • uncompress the response stram ;
  • read the response stream to interpret the results in the SOAP envelop.

Implementing ZHttpWebRequest

WebRequest's class diagramThe first step is to implement a class that handle the HTTP request, adding the header that inform the server that the client understands gzip or deflate answers. If the server does not know either of these compression algorithms, the data are sent uncompressed.

public class ZHttpWebRequest : System.Net.WebRequest { private HttpWebRequest request; private System.Uri uri; internal ZHttpWebRequest(System.Uri uri) { string s = uri.AbsoluteUri.Substring(1); // remove the leading z this.uri = uri; request = (HttpWebRequest)WebRequest.Create(s); // tell the HTTP server that the client accept compressed data request.Headers.Add("Accept-Encoding", "gzip, deflate"); }

The next step consists in returning the ZHttpWebResponse in the GetResponse method, so that it can uncompress the data sent by the HTTP server.

public override System.Net.WebResponse GetResponse() { ZHttpWebResponse response = null; // create the appropriate response object response = new ZHttpWebResponse(request, uri); return response; }

Finally, all the others overloaded methods should return the result of the internal HttpWebRequest object.

// for all the other overridable functions, redirect the call // to the private HttpRequest object, as shown above public override void Abort() { request.Abort(); // redirect the call } ... }

Implementing ZHttpWebResponse

WebResponse's class diagramTo handle the response, the ZHttpWebResponse object derives from WebResponse and retrieves the regular HttpResponse object from the HTTP request object.

public class ZHttpWebResponse : WebResponse { private HttpWebResponse response; private System.Uri uri; internal ZHttpWebResponse(WebRequest request, System.Uri uri) { this.uri = uri; response = (HttpWebResponse)request.GetResponse(); }

The GetResponseStream method does all the uncompressing job, whether the response is gzip enconded, deflate encoded or not encoded at all.

public override Stream GetResponseStream() { // select the right decompression stream if(response.ContentEncoding=="gzip") { return new GZipInputStream(response.GetResponseStream()); } else if(response.ContentEncoding=="deflate") { return new InflaterInputStream(response.GetResponseStream()); } else { return response.GetResponseStream(); } }

The next step is to override ResponseUri to return the zhttp Uri. Then, all the others overloaded methods should return the result of the internal HttpWebRequest object.

public override System.Uri ResponseUri { get { return uri; } } // for all the other overridable functions, redirect the call // to the private HttpRequest object, as shown above public override void Close() { response.Close(); } ... }

Registering the zhttp protocol

The Web requests are handled through a class factory that instanciate the WebRequest objects able to handle the uri. So, http:// is handled by HttpWebRequest, file:// by FileWebRequest, etc.

The following class, that implements IWebRequestCreate, is used by the register function to instanciate the ZHttpWebRequest objects.

class ZHttpWebRequestCreate : IWebRequestCreate { /// <summary> /// Create the WebRequest object able to handle the Uri /// </summary> /// <param name="uri">the requested Uri</param> /// <returns>The WebRequest object</returns> public System.Net.WebRequest Create(System.Uri uri) { System.Net.WebRequest request = new ZHttpWebRequest(uri); return request; } }

Then, let the ZHttpProtocol class wrap the call to the registration function.

public class ZHttpProtocol { /// <summary> /// Register the protocol /// </summary> /// <returns></returns> static public bool Register() { return WebRequest.RegisterPrefix("zhttp", new ZHttpWebRequestCreate()); } }

So now, to register the zhttp protocol, we just have to call ZHttpProtocol.Register in our code, before the first call to the web services, in the Main function for instance.

// register the protocol ZHttpProtocol.Register();

Changing the WebService's Uri

In order to use the zhttp protocol, the Uri of the WebService objects must be changed by inserting a "z" in front of the original Uri.

// initiliaze the WebService MyWebService ws = new MyWebService(); ws.Url = "z" + ws.Url; // call the methods ...

Et voilà !

Configuring IIS 5.0 Server to compress aspx and asmx files

Once the compression is activated for the IIS 5.0 server, run the following commands to add the aspx and asmx to the file types list the compression filter have to handle:

CSCRIPT.EXE ADSUTIL.VBS 
  SET W3Svc/Filters/Compression/GZIP/HcScriptFileExtensions 
  "dll" "asp" "aspx" "asmx"¶
¶
CSCRIPT.EXE ADSUTIL.VBS¶
  SET W3Svc/Filters/Compression/DEFLATE/HcScriptFileExtensions 
  "dll" "asp" "aspx" "asmx"¶
¶
IISRESET.EXE¶

Some useful links...

Revision history...

daterévision
18/01/2006 00:00Binary file update
The assembly is now having a strong name in order to be reference by assemblies with strong names.
26/01/2004 00:00Source file update
Implementation of the property Headers at the line 374 to avoid a NotSupportedException to be raised. (Thanks to Jeff Evans for reporting and correcting the bug).

all the informations here are provided as is, without any warranty of any kind.
© 2024 Flow Group SAS - Flow Group est une marque déposée de GL Conseil SA.