In Silverlight/WPF and WPF there’s today a WebClient class for making webrequests. Under the covers it creates HttpWebRequest for sending the request and HttpWebResponse for handling the response coming back from the server. In an older blogpost, I created a custom WebClient for WP7 that added support for GZIP compression this way.
However the default WebClient doesn’t actually create an “HttpWebRequest/Response” object, since this is an abstract class. What it really does is create internal subclasses that is then used. This is handled by the WebRequestCreator static class which really creates these classes for you. However a less-known feature is that you can actually tell your application that you want to use a specific client for handling the web request and responses for specific domains. You might actually already have fiddled with this in Silverlight if you wanted to explicitly let Silverlight handle the web requests instead of handing it off to the hosting browser control using the following statement:
WebRequest.RegisterPrefix("http://www.mydomain.com/", WebRequestCreator.ClientHttp);
This call makes all requests to www.mydomain.com go through the ClientHttp. As mentioned it’s possible to make your own requestor and completely intercept ANY requests made by WebClient!
If you have your own HttpWebRequest implementation ‘MyHttpWebRequest’, this would look something like this:
public static class MyWebRequestCreator
{
private static IWebRequestCreate myCreator;
public static IWebRequestCreate MyHttp
{
get
{
if (myCreator == null)
{
myCreator = new MyHttpRequestCreator();
}
return myCreator;
}
}
private class MyHttpRequestCreator : IWebRequestCreate
{
public WebRequest Create(Uri uri)
{
return new MyHttpWebRequest(uri);
}
}
}
So now you can just call:
WebRequest.RegisterPrefix("http://", MyWebRequestCreator.MyHttp);
WebRequest.RegisterPrefix("https://", MyWebRequestCreator.MyHttp);
…and ALL web requests to http or https websites, will be routed through your MyHttpWebRequest class (which you granted still have to build). This class could just wrap the built-in ClientHttpWebRequest and you can modify/add/remove/decode stuff to your pleasing. This is awesome for test framework mock ups, but it’s also really neat for the GZIP WebClient control I mentioned earlier. Why? Well to use my GZipWebClient, you would have to go through all your code and change:
WebClient client = new WebClient();
to
WebClient client = new SharpGIS.WebClient();
This can be a lot of work, and even if you did that, what about all the 3rd party libraries you use, where you can’t go in and change that? Well enter RegisterPrefix! Do you want GZIP support in Hammock? Done! Do you want GZIP support in RestSharp? Done!* Do you want GZIP support in [insert favorite API here]? Done!
*Update: Actually this might not be the case. Some libraries uses some features that either is not possible to implement with the custom HttpWebRequest (like UserAgent), and I didn’t add support for Cookies as well. Both of these are for instance used by RestSharp.
So I went ahead and updated my Nuget Package for the GZipWebClient, so go grab v1.1, and you will only have to add 1-2 LINES OF CODE, and just execute it ONCE (for instance at startup), and EVERYTHING WebClient will be enhanced with GZIP compression. You can also grab the updated source on the original blogpost here.
I really have to give some credit to my co-worker Anargyros for this one, who mentioned that it might be possible to do it this way. Go follow him on twitter and give him some twitter love @tomahawk1187