How to add cookies to WebRequest?

I am trying to unit test some code, and I need to to replace this:

  HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create( uri );
  httpWebRequest.CookieContainer = new CookieContainer();

with

  WebRequest webRequest = WebRequest.Create( uri );
  webRequest.CookieContainer = new CookieContainer(); 

Basically, how do I get cookies into the request without using a HttpWebRequest?


Solution 1:

Based on your comments, you might consider writing an extension method:

public static bool TryAddCookie(this WebRequest webRequest, Cookie cookie)
{
    HttpWebRequest httpRequest = webRequest as HttpWebRequest;
    if (httpRequest == null)
    {
        return false;
    }

    if (httpRequest.CookieContainer == null)
    {
        httpRequest.CookieContainer = new CookieContainer();
    }

    httpRequest.CookieContainer.Add(cookie);
    return true;
}

Then you can have code like:

WebRequest webRequest = WebRequest.Create( uri );
webRequest.TryAddCookie(new Cookie("someName","someValue"));

Solution 2:

WebRequest is an abstract class that does not have a CookieContainer property. In addition you can't use the Headers collection (not implemented exception) so any attempt like webRequest.Headers.Add("Cookie", "...") will fail.

Sorry, but you have no chance to use cookies with WebRequest.

Stick on HttpWebRequest and add/edit as many cookies you like using its Headers collection!

Solution 3:

Try with something like this:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/default.html");
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(new Cookie("ConstoCookie", "Chocolate Flavour"));

Solution 4:

dlev's answer ended up working, but I had problems implementing the solution ("The parameter '{0}' cannot be an empty string."), so I decided to write the full code in case anybody else has similar problems.

My goal was to get the html as a string, but I needed to add the cookies to the web request. This is the function that downloads the string using the cookies:

public static string DownloadString(string url, Encoding encoding, IDictionary<string, string> cookieNameValues)
{
    using (var webClient = new WebClient())
    {
        var uri = new Uri(url);
        var webRequest = WebRequest.Create(uri);
        foreach(var nameValue in cookieNameValues)
        {
            webRequest.TryAddCookie(new Cookie(nameValue.Key, nameValue.Value, "/", uri.Host));
        }                
        var response = webRequest.GetResponse();
        var receiveStream = response.GetResponseStream();
        var readStream = new StreamReader(receiveStream, encoding);
        var htmlCode = readStream.ReadToEnd();                
        return htmlCode;
    }
}   

We are using the code from dlev's answer:

public static bool TryAddCookie(this WebRequest webRequest, Cookie cookie)
{
    HttpWebRequest httpRequest = webRequest as HttpWebRequest;
    if (httpRequest == null)
    {
        return false;
    }

    if (httpRequest.CookieContainer == null)
    {
        httpRequest.CookieContainer = new CookieContainer();
    }

    httpRequest.CookieContainer.Add(cookie);
    return true;
}

This is how you use the full code:

var cookieNameValues = new Dictionary<string, string>();
cookieNameValues.Add("varName", "varValue");
var htmlResult = DownloadString(url, Encoding.UTF8, cookieNameValues);