Our virtual home

InternetGetCookie() in .NET

Sometimes there is a need to send cookies over the line on a call to HttpWebRequest.GetResponse(). The documentation about HttpWebRequest.CookieContainer: "... The CookieContainer property provides an instance of the CookieContainer class that contains the cookies associated with this request." That's really nice to have this support already there! But: how I get it setup on the first request? Often users already have a dozen cookies within their temporary internet files folder managed by Internet Explorer. How can I reuse these?
Bad news: there is no managed code support in the .NET Framwork to get them. Good news: we can use the Windows API support provided in wininet.dll to retrieve the cookies: InternetGetCookie(). So we can define the Interop declaration as follows:

[DllImport("wininet.dll", CharSet=CharSet.Auto , SetLastError=true)]
public static extern bool InternetGetCookie (
 
string url, string name, StringBuilder data, ref int dataSize);

That's it. To wrap the call we define a wrapper function:

private static string RetrieveIECookiesForUrl(string url) {
    StringBuilder cookieHeader =
new StringBuilder(new String(' ', 256), 256);
   
int datasize = cookieHeader.Length;
   
if (!InternetGetCookie(url, null, cookieHeader, ref datasize)) {
       
if (datasize < 0) 
           
return String.Empty;
        cookieHeader =
new StringBuilder(datasize); // resize with new datasize
        InternetGetCookie(url,
null, cookieHeader, ref datasize);
   
}
   
return cookieHeader.ToString();
}

OK, now we have the cookie content string, that looks usually like this: "KEY=Value; KEY2=what ever". Now we simply create managed cookies by creating instances of System.Net.Cookie. But stop! Did we really have to parse the cookie content string (aka cookie headers) to create the instances?
Again, good news: no, we did not have to do this. There is already build in support provided by the CookieContainer class we also need to set on the HttpWebRequest! The code:

public static CookieContainer GetCookieContainerForUrl(Uri url) {
    CookieContainer container =
new CookieContainer();
   
string cookieHeaders = RetrieveIECookiesForUrl(url.AbsoluteUri);
   
if (cookieHeaders.Length > 0) {
        try { container.SetCookies(url, cookieHeaders); } catch (CookieException){}
    }
   
return container;
}

Done :-)

» Similar Posts

  1. How to prevent the configuration file watcher thread in Microsoft Enterprise Library 3.1
  2. Why .NET Remoting does not have a RemotingConfiguration.Reset() ?
  3. More to know about .NET Timers

» Comments

  • Will avatar

    Thanks for the code snippets - I was unaware of the Wininet funcion and this was a big help!

    Will — April 4, 2006 12:59
  • Richard avatar

    This code doesn't work. For some unknown reason, the CookieContainer.SetCookies method expects each cookie to be separated by a comma rather than a semi-colon. As a result, only the first cookie will be parsed. Also, if the cookie name or value contains a comma, you will get a System.Net.CookieException indicating that the cookie format is invalid.

    Richard — November 7, 2006 7:57
  • TorstenR avatar

    Richard: you are right. We have the code yet fixed for the current RSS Bandit code, but I did not updated the post. So see the update.

    TorstenR — November 7, 2006 9:43
  • Andreas Olipitz avatar

    This code works - somehow^^ - Many thanks from austria.

    Andreas Olipitz — Februar 27, 2007 7:13
  • JimH avatar

    Blindly replacing the semicolon in the httpCookies string with a comma allows all cookies (subcookies) to be sent in the request. Perhaps this could break a cookie that intentionally had a semicolon, but works for my purposes:string cookieHeaders2 = cookieHeaders.Replace(';', ',');container.SetCookies(url, cookieHeaders2);

    JimH — April 29, 2007 10:04
  • Comments are closed