Join us!
Want to join the team?

We would love to get to know you

Are you looking for an employer who cares about you as a person and where you feel involved in everything that concerns you? Welcome to JellyHive!
Who are we? We are a successful IT consultant company and our philosophy is that the company is our employees.
Who are you? You are a system developer (fullstack, frontend, backend), and/or maybe also a scrum master, test lead, devops etc.
What we offer you Participation in developing the company with generous benefits.


Upload your cv Supported filetypes are: .pdf, .doc and .docx
Hide

CookieContainer bug in Windows Phone 8.x

Debugger Result CookieContainer

If you have used the Windows Phone CookieContainer for stateful communication towards a site / service that does not have a www prefix (which of course many of them don’t), you may have noticed that this does not work. A bug in the CookieContainer stores the domain with an erroneous name making it impossible for the cookies to be found at lookup on the same domain occurs.

The example above shows how the domain name for http://mgmobil.golf.se is stored with a leading “.” in the collection.

The bug is known by Microsoft and has existed before in previous versions of the .NET Framework (discussed here http://tinyurl.com/cookiecontainerbug771651 and herehttp://tinyurl.com/cookiecollectionbug ). I was hoping that the bug would be resolved with Microsoft now releasing Windows Phone 8.1 and at the same time what is called Universal Apps. Unfortunately it seems not to be the case, which will involve incompatible and opaqueness functionality between Windows Phone and Windows 8, which does not hold the same problem.

A solution to this problem is to single-handedly manage cookies and write these in the header when calling against sites that do not have the www prefix. For HttpClient (which exists as default in WP 8.1 or https://www.nuget.org/packages/Microsoft.Net.Http for WP8) I have written custom HttpClientHandler which can be used in one its constructors.

public class CookieEnabledHttpClientHandler : HttpClientHandler { private readonly CookieCollection cookieCollection;

public CookieEnabledHttpClientHandler() { UseCookies = true; CookieContainer = new CookieContainer(); cookieCollection = new CookieCollection(); }

protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if(!UseCookies) return await base.SendAsync(request, cancellationToken);

SetCookies(request);

var response = await base.SendAsync(request, cancellationToken);

ParseResponse(response);

return response; }

public void SetCookies(HttpRequestMessage request) { if (CookieContainer.GetCookies(request.RequestUri.GetLeftPart()).Count > 0) return;

if (cookieCollection.Count == 0) return;

var cookieString = new StringBuilder();

foreach (var cookie in cookieCollection) { cookieString.Append(cookie); cookieString.Append(“; “); }

request.Headers.Add(“cookie”, cookieString.ToString().TrimEnd(‘ ‘, ‘;’)); }

public void ParseResponse(HttpResponseMessage responseMessage) { if (CookieContainer.GetCookies(responseMessage.RequestMessage.RequestUri.GetLeftPart()).Count > 0) return;

if (!responseMessage.Headers.Contains(“Set-Cookie”)) return;

var cookies = responseMessage.Headers.GetValues(“Set-Cookie”);

foreach (var cookie in cookies) { foreach (var cookieString in Regex.Split(cookie, “, “)) { var newCookie = new Cookie();

foreach (var value in cookieString.Split(‘;’). Select(cookiePartString => cookiePartString.Trim().Split(‘=’))) { switch (value[0].ToLower()) { case “expires”: newCookie.Expires = DateTime.Parse(value[1]); continue; case “domain”: newCookie.Domain = value[1]; continue; case “path”: newCookie.Path = value[1]; continue; case “httponly”: newCookie.HttpOnly = true; continue; default: newCookie.Name = value[0]; newCookie.Value = value[1]; continue; } }

cookieCollection.Add(newCookie); } } } }

The HttpHandler will check if the cookies are found for the specific domain and in that case not use the custom functionality. The handler can be called using the HttpClient like this:

var client = new HttpClient(new CookieEnabledHttpClientHandler()); 

Comments