Accessing a WebService's WebRequest and WebResponse in NetCF

One common question regarding the .NET Compact Framework involves the availability of the WebRequest and WebResponse objects used by the SOAP client when making a web service call.  If you are using version 1 of the .NET Compact Framework (1.0.2268.0), these objects are not available to your code.  Since the release of Service Pack 1 (1.0.3111.0), it is become possible to gain access to these objects.

Why access the underlying request and response?

There are a number of reasons why access to the WebRequest and/or WebResponse is useful.  Custom headers can be used for simple client identification, cookies can be implemented, etc.  I'm sure many other interesting scenarios will come to mind.

A few notes...

  • Most web service client proxy classes are autogenerated (either by WSDL.exe or Add Web Reference in Visual Studio .NET).  Changes to the generated code files will be lost the next time they are regenerated (ex: "Update web reference" in Visual Studio).
  • GetWebRequest and GetWebResponse are protected methods on WebClientProtocol (a parent class to SoapHttpClientProtocol) and are called by the SOAP client class library, not by application code.

Keeping the above in mind, I recommend implementing your customizations in a derived class.  Reference your derived class in your application, instead of the generated one.  This way, you can update your web service client proxy as often as you need, without risk of losing your custom code.

Below is a simple example that sets a custom HTTP header on the underlying WebRequest. 

Web service client proxy
public class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {{    // autogenerated code will be in here}

Derived proxy class
public class MyCustomWebService : MyWebService{    private String m_HeaderName;    private String m_HeaderValue;

    //----------------
    // GetWebRequest
    //
    // Called by the SOAP client class library
    //----------------  
    protected override WebRequest GetWebRequest(Uri uri)
    {
        // call the base class to get the underlying WebRequest object
        HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(uri);
   
        if(null != this.m_HeaderName)
        {
            // set the header
            req.Headers.Add(this.m_HeaderName, this.m_HeaderValue);
        }      
   
        // return the WebRequest to the caller
        return (WebRequest)req;
    }

    //----------------
    // SetRequestHeader
    //
    // Sets the header name and value that GetWebRequest will add to the
    // underlying request used by the SOAP client when making the
    // we method call
    //----------------  
    public void SetRequestHeader(String headerName, String headerValue)
    {
        this.m_HeaderName = headerName;
        this.m_HeaderValue = headerValue;
    }  
}

Simple client application
class MyApplication{    public static void Main()    {        // create the web service client object        MyCustomWebService service = new MyCustomWebService();

        // set the custom header
        service.SetRequestHeader("ACustomHeader", "Go Huskies!");

        // call the desired web service method       
        Object result = service.ExampleMethod( ... );       
    }
}

GetWebResponse can be overriden similarly.  As you can see, it is easy to gain access to the underlying WebRequest and WebResponse objects.  Please remember that GetWebRequest and GetWebResponse are not called by application code -- they are methods you implement for the SOAP client to call.

Have fun!
-- DK

Disclaimer(s):
This posting is provided "AS IS" with no warranties, and confers no rights.

[Edit: fix version number]