无法使用WebClient接收cookie

时间:2013-05-20 10:43:28

标签: c# windows-phone-7 webclient session-cookies jsessionid

纠正我,如果我的思想错了。

据我所知,任何新的WebClient类实例都会启动一个新会话,生成新的会话ID。

为了防止这种情况,我应该从第一次使用中收到会话ID,然后将其传递给WebClient的所有新实例。 (对于“GET”方法,只需将其作为任何其他参数添加到请求中)

理论上,它可以使用类来完成,如下所示:

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;
    }
}

然而,这对jsessionid cookie无效,这种方法存在两个问题。

  1. 我无法在保存的CookieContainer中看到jsessionid值。
  2. 即使我使用不同的方法(例如下面的方法)收到此值,然后将此值添加到reqeust uri中作为& jsessionid = someValue ,这也无济于事。
  3. 我已经多次检查过了,每当我在Windows Phone中发送此类请求时,响应都会有一个不同且独特的jsessionid。

    但是,如果我在浏览器中写入此类请求,则响应返回正确的jsessionid。


    以下代码允许从Windows Phone中的响应接收jsessionid值(使用HttpWebRequest而不是WebClient),但不能解决问题:

                            // 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);
    

1 个答案:

答案 0 :(得分:1)

是的,所以如果jsessionid值可以使用提供的方式接收,那么解决方案就是使用HttpWebRequest作为ExtendedWebClient以某种方式忽略jsession值。

            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

另一方面,在Windows Phone中也不起作用的是,您无法轻松序列化CookieCollection类型值。因此,我决定在IsolatedStorage设置中存储String类型的JSESSIONID值而不是它,并创建一个静态类StoredCookieCollection,它将在应用程序工作期间存储CookieCollection。

因此,当您收到jsessionid值时,它将作为字符串保存在设置中,并作为CookieCollection保存在静态类中:

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

这种方法将真正迫使应用程序在单个会话中工作。

也许,使用CookieCollection序列化有一个更优雅的解决方案,但我找不到它。