Reputation: 81
I have a production app that makes two calls via HttpWebRequest. The first call sets a session and receives cookies back to maintain the session, the second call is for data from the api. The responses are httponly. I am using a shared CookieContainer between the two calls, but the second call always fails. I narrowed the problem down to the cookies not being sent in the second request. I've used Network Monitor to watch the traffic, and if I explicitly set the cookies in the second request (see code below), the call succeeds. Anybody have any ideas on this issue? I need to figure out how to get it to work with the shared CookieContainer.
private string URL_01 = "https:// [...]";
private string URL_02 = "https:// [...]";
private CookieContainer _cookieContainer = new CookieContainer();
private NetworkCredential nc = new NetworkCredential("username", "password");
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
HttpWebRequest request = HttpWebRequest.CreateHttp(URL_01);
request.CookieContainer = _cookieContainer;
request.Credentials = nc;
request.UseDefaultCredentials = false;
request.BeginGetResponse(new AsyncCallback(HandleResponse), request);
}
public void HandleResponse(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
if (request != null)
{
using (WebResponse response = request.EndGetResponse(result))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string data = reader.ReadToEnd();
// gets returned data and deserializes it to an object
SessionObject so = JsonConvert.DeserializeObject<SessionObject>(data);
if (so.DeviceAPI.Session == "true")
{
// make a second call for the data
HttpWebRequest requestData = HttpWebRequest.CreateHttp(URL_02);
// when this is used, the call fails
requestData.CookieContainer = _cookieContainer;
// when this is used, the call works
//requestData.Headers[HttpRequestHeader.Cookie] = "_key=value; _secret=value";
requestData.Credentials = nc;
requestData.BeginGetResponse(new AsyncCallback(DataResponse), requestSongData);
}
}
}
}
}
public void DataResponse(IAsyncResult DataResult)
{
HttpWebRequest requestData = DataResult.AsyncState as HttpWebRequest;
if (requestData != null)
{
using (WebResponse dataResponse = requestData.EndGetResponse(DataResult))
{
using (StreamReader reader = new StreamReader(dataResponse.GetResponseStream()))
{
string data = reader.ReadToEnd();
// do something with the data
}
}
}
}
}
}
Upvotes: 5
Views: 2720
Reputation: 81
This problem is a known issue with the CookieContainer when the domain name has no "www" on it. The CookieContainer is expecting a "www" and does not identify existing cookies for the domain.
The work around was to read the cookies from the response headers and add them to any other requests.
Was considered for a fix for Mango, but got pushed out.
Jeff
Upvotes: 3
Reputation: 4268
I had his issue and it seemed to be with using an old cookie container. Just create a new one by Iterating through the old one, and creating new cookies.
Step 1. Create a dictionary to store cookies.
//create a dictionary to store your persistent cookies
public static Dictionary<string, Cookie> CookieCollection { get; set; }
Step 2. Add the cookies you have stored, onto the webrequest before it's sent off.
var request = WebRequest.Create(...);
//add the cookies you have in your persistent cookie jar
foreach (KeyValuePair<string, Cookie> cookie in _collection)
{
try
{
request.CookieContainer.Add(request.RequestUri, new Cookie(cookie.Value.Name, cookie.Value.Value));
}
catch
{
}
}
Step 3. Saving the Cookies
ResponseCallback(...) {
//update your local cookie list as required
foreach (Cookie clientcookie in response.Cookies)
{
if (!_collection.ContainsKey(clientcookie.Name))
_collection.Add(clientcookie.Name, clientcookie);
else
_collection[clientcookie.Name] = clientcookie;
}
}
Upvotes: 0