Question

Correct me, if I'm wrong in my thoughts.

As I understand, any new instance of WebClient class will start a new session, generating the new session id.

To prevent this, I should receive a session id from the first usage, and then pass it to all new instances of WebClients. (For "GET" method just can be added to the request as any other parameter)

Theoretically, it can be done, using class, like this:

public class ExtendedWebClient : WebClient
{
    public CookieContainer CookieContainer { get; private set; }

    [SecuritySafeCritical]
    public ExtendedWebClient()
    {
        this.CookieContainer = new CookieContainer();
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);

        if (request is HttpWebRequest)
            (request as HttpWebRequest).CookieContainer = this.CookieContainer;

        return request;
    }
}

However that doesn't work with jsessionid cookie, there are two problems with this approach.

  1. I can't see the jsessionid value in saved CookieContainer.
  2. Even if I'll receive this value using a different approach, like the one below, and then add this value to the reqeust uri as &jsessionid=someValue, that won't help.

I've checked several times, and any time I send such request in Windows Phone, the response has a different and unique jsessionid.

However, if I write such request in browser, the response returns with a correct jsessionid.


The following code allows to receive the jsessionid value from response in Windows Phone(uses HttpWebRequest instead of WebClient), but doesn't solve the problem :

                        // working with some uri
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
                        request.Method = "GET";
                        request.CookieContainer = new CookieContainer();
                        request.BeginGetResponse(asynchronousResult =>
                            {
                                try
                                {
                                    using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult))
                                    {
                                        CookieCollection cookies = response.Cookies;
                                        foreach (Cookie c in cookies)
                                        {
                                            if (c.Name == "JSESSIONID")
                                                // jsessionid value is here. Can be saved & stored somewhere
                                        }
                                        response.Close();
                                    }


                                catch (Exception e)
                                {
                                    // handling exception somehow
                                }
                            }
                        , request);
Was it helpful?

Solution

Right, so if jsessionid value can be received using the way, provided in question, the solution will be to use HttpWebRequest as ExtendedWebClient somehow ignores the jsession value.

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(new Uri(url, UriKind.Absolute), StoredCookieCollection._CookieCollection);
            request.BeginGetResponse(new AsyncCallback(GetSomething), request);

           private void GetSomething(IAsyncResult asynchronousResult)
           {
              // do something
           }

           // where in url a jsession value is added to the request as &jsessionid=value

The other thing, that also doesn't work in Windows Phone is, that you can't serialize CookieCollection type value so easily. So, I decided to store a String type JSESSIONID value in IsolatedStorage settings instead of it, and create a static class StoredCookieCollection, that will store CookieCollection during the app work.

So, when you receive a jsessionid value, it is saved in settings as string, and saved in static class as CookieCollection :

using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult))
                                    {
                                        CookieCollection cookies = response.Cookies;
                                        StoredCookieCollection._CookieCollection = cookies;
                                        ...
                                    }

That approach will really force the app to work in single session.

Perhaps, there is a more elegant solution with CookieCollection serialization, but I couldn't find it out.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top