Tuesday, May 29, 2007

Maintaining Web service SessionState with .NET Compact Framework v2

For a project on which i'm working i needed to interact with a Web service implemented using Axis (Java) from an application running on a Windows Mobile 5 device. I've received instructions that before invoking the main Web methods, i needed to invoke the "authenticate" web method to enable access.

Unfortunatly no matter what i tried, i wasn't able to retrieve any data from the main Web methods. I got the tip from the Web service author to check SessionState. Apparently the Compact Framework doesn't provide any solutions for Cookie Sessionstate out-of-the-box. The most obvious class which is present in the full .Net framework, the CookieManager-class unfortunatly isn't supported by the Compact Framework. With Google i found some posts from people which had the same problem.

A collegue of mine suggested that subclassing the Web service-proxy might give a solution, which it did. With only some minor code you can enable Sessionstate in the Compact Framework v2. I ended up with this solution. Instead of instantiating the original WSDL-generated Web service proxy class you should subclass it in this way:
public class StatefullServiceClass : OriginalServiceClass
{


#region Private fields
/// <summary>
/// This field contains the received session cookie
/// </summary>
private string cookie = null;
#endregion



#region Private constants
/// <summary>
/// Http-Header for the request SessionCookie
/// </summary>
private const string REQUESTHEADER_SESSIONCOOKIE = "Cookie";
/// <summary>
/// Http-header for the response SessionCookie
/// </summary>
private const string RESPONSEHEADER_SESSIONCOOKIE = "Set-cookie";
#endregion



#region Private methods
private void ProcessResponse(System.Net.HttpWebResponse response)
{
// Is the cookie present in the response?
if (response.Headers.Get(RESPONSEHEADER_SESSIONCOOKIE) != null)
{ // Yes
// Store the cookie
cookie = response.Headers.Get(RESPONSEHEADER_SESSIONCOOKIE);
}
}
#endregion



#region Protected overrides
/// <summary>
/// This override will tweak the request to allow Session-cookies
/// </summary>
/// <param name="uri"></param>
/// <returns>The tweaked request</returns>
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)
base.GetWebRequest(uri);
// Is the session cookie cached?
if (cookie != null)
{ // Yes
// Add the sessioncookie to the request
request.Headers.Add( REQUESTHEADER_SESSIONCOOKIE, cookie );
}
return request;
}



/// <summary>
/// This override will tweak the response to allow Session-cookies
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
protected override System.Net.WebResponse
GetWebResponse(System.Net.WebRequest request)
{
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)
base.GetWebResponse(request);
ProcessResponse(response);
return response;
}



/// <summary>
/// This override will tweak the response to allow Session-cookies
/// </summary>
/// <param name="request"></param>
/// <param name="result"></param>
/// <returns></returns>
protected override System.Net.WebResponse
GetWebResponse(System.Net.WebRequest request, IAsyncResult result)
{
System.Net.HttpWebResponse response =
(System.Net.HttpWebResponse) base.GetWebResponse(request, result);
ProcessResponse(response);
return response;
}
#endregion


}
Instead of instantiating the original Web service proxy class, you should instantiate the subclassed version. And voila! SessionState!

No comments:

Post a Comment