Cookies, Cookie Collection and CookieContainer

When using System.Net or Web Services, you might want to receive or send cookies, perhaps for session state
maintenance or in some rare situations for proxy authentication.
The first thing we are tempted to do is to access
WebResponse.Cookies collection. But then it returns no cookies. Why?
It turns out that unless you assign a CookieContainer to the WebRequest, you won't be able to get the
WebResponse.Cookies. It is not very intuitive. Why would I need to create a cookie container to get cookies?
Notice that you need to create a cookie container but then you get cookie collection from WebResponse.
Here is some sample code

CookieContainer CC = new CookieContainer();
HttpWebRequest Req = (HttpWebRequest) WebRequest.Create("https://localhost/CookieTest/first.aspx");
Req.Proxy = null;
Req.UseDefaultCredentials = true;
//YOU MUST ASSIGN A COOKIE CONTAINER FOR THE REQUEST TO PULL THE COOKIES
Req.CookieContainer = CC;
Res = (HttpWebResponse)Req.GetResponse();
//DUMP THE COOKIES
Console.WriteLine("----- COOKIES -----");
if(Res.Cookies != null && Res.Cookies.Count != 0)
{
foreach(Cookie c in Res.Cookies)
{
Console.WriteLine("\t" + c.ToString());
}
}
else
{
Console.WriteLine("No Cookies");
|}

OK fine you might say - but what is the difference between CookieCollection and a CookieContainer?
They kind of look the same.  The difference is that the CookieCollection is the cookies obtained for the
SPECIFIC request.  CookieContainer is designed to be a store of all the cookies for one more requests.
To that extent, the CookieContainer is designed to be a hashtable of "domain - CookieCollection" pairs.

What this means is that for the next requests you create, you can safely assign the cookiecontainer from the previous
request. But then you might be wondering whether we send the cookies that we are not supposed to. Fear not.
The CookieContainer is designed to be safe.
When the second request is sent the we look at the URI and the path you are using and send only those cookies
that we can safely send as per the RFC.

Here is the complete sample for Cookies

using System;
using System.Threading;
using System.Net;
using System.Text;
using System.IO;

public class Test
{

 public static void Main(string[] args)
{
Stream s = null;
StreamReader sr = null;
HttpWebResponse Res = null;
CookieContainer CC = new CookieContainer();
try
{
//----------------------------------------------------
//FIRST REQUEST
//----------------------------------------------------
HttpWebRequest Req = (HttpWebRequest) WebRequest.Create("https://localhost/CookieTest/first.aspx");
Req.Proxy = null;
Req.UseDefaultCredentials = true;

//YOU MUST ASSIGN A COOKIE CONTAINER FOR THE REQUEST TO PULL THE COOKIES
Req.CookieContainer = CC;

   Res = (HttpWebResponse)Req.GetResponse();

//DUMP THE COOKIES
Console.WriteLine("----- COOKIES -----");
if(Res.Cookies != null && Res.Cookies.Count != 0)
{
foreach(Cookie c in Res.Cookies)
{
Console.WriteLine("\t" + c.ToString());
}
}
else
{
Console.WriteLine("No Cookies present");
}

s = Res.GetResponseStream();
sr = new StreamReader(s, Encoding.ASCII);
Console.WriteLine("----- RESPONSE -----");
Console.WriteLine("\t" + sr.ReadToEnd());

   //----------------------------------------------------
//SECOND REQUEST
//----------------------------------------------------   

   Req = (HttpWebRequest) WebRequest.Create("https://localhost/CookieTest/second.aspx");
Req.Proxy = null;
Req.UseDefaultCredentials = true;

//TO TRANSFER COOKIES TO THE NEXT PAGE
Req.CookieContainer = CC;

   Res = (HttpWebResponse)Req.GetResponse();

//DUMP THE COOKIES
Console.WriteLine("----- COOKIES -----");
if(Res.Cookies != null && Res.Cookies.Count != 0)
{
foreach(Cookie c in Res.Cookies)
{
Console.WriteLine("\t" + c.ToString());
}
}
else
{
Console.WriteLine("No Cookies present");
}

s = Res.GetResponseStream();
sr = new StreamReader(s, Encoding.ASCII);
Console.WriteLine("----- RESPONSE -----");
Console.WriteLine("\t" + sr.ReadToEnd());

}
catch(Exception ex)
{
Console.WriteLine(ex);
}
finally
{
if(sr != null) sr.Close();
if(s != null) s.Close();
}
}
}

Hope you find this useful. Let me know your comments
Also let me know what other topics you want me to blog about.

Just a note that I will be speaking at the PDC 2005 doing a Tips and Tricks
session on System.Net 2.0. I will be covering Tracing, X509 Certificates, Kerberos auth,
SMTP with embedded resources, etc. If there is a particular topic that if interest to you
let me know.

Durgaprasad Gorti
Test Lead
System.Net