27

I want to tunnel through an HTTP request from my server to a remote server, passing through all the cookies. So I create a new HttpWebRequest object and want to set cookies on it.

HttpWebRequest.CookieContainer is type System.Net.CookieContainer which holds System.Net.Cookies.

On my incoming request object:

HttpRequest.Cookies is type System.Web.HttpCookieCollection which holds System.Web.HttpCookies.

Basically I want to be able to assign them to each other, but the differing types makes it impossible. Do I have to convert them by copying their values, or is there a better way?

burning_LEGION
  • 13,246
  • 8
  • 40
  • 52
Mike
  • 5,560
  • 12
  • 41
  • 52

3 Answers3

37

Here's the code I've used to transfer the cookie objects from the incoming request to the new HttpWebRequest... ("myRequest" is the name of my HttpWebRequest object.)

HttpCookieCollection oCookies = Request.Cookies;
for ( int j = 0; j < oCookies.Count; j++ ) 
{
    HttpCookie oCookie = oCookies.Get( j );
    Cookie oC = new Cookie();

    // Convert between the System.Net.Cookie to a System.Web.HttpCookie...
    oC.Domain   = myRequest.RequestUri.Host;
    oC.Expires  = oCookie.Expires;
    oC.Name     = oCookie.Name;
    oC.Path     = oCookie.Path;
    oC.Secure   = oCookie.Secure;
    oC.Value    = oCookie.Value;

    myRequest.CookieContainer.Add( oC );
}
David
  • 34,223
  • 3
  • 62
  • 80
  • 1
    I think this technique will work, but I was really hoping for a solution that wouldn't involve copying each value over. – Mike Aug 13 '09 at 12:58
  • whats with the try with the empty catch? – CRice Jun 14 '11 at 00:37
  • I think one problem may arise in setting `expires time`. Because We can not get `Expires` time from Request Variable. It always return `new DateTime()` object which is a `minimum date time`. So If you set this time to `Expires` property than I think cookie will get removed from Response object. @David – shashwat Aug 20 '12 at 09:08
  • I was getting a nullreference exception at the request.CookieContainer.Add(oc). I tried it by getting via INDEX and by key. WHat am i doing wrong that is different? – Fallenreaper Oct 26 '12 at 20:08
  • Be carefull if, like me, you are converting a Cookie to a HttpCookie. The Path field has a different default value in both classes, and if it is empty in Cookie you don't want to set it empty in HttpCookie, as this will default the path of the response. – pauloya Apr 24 '14 at 10:14
  • An exception is thrown due to encoding issues. "The "Value = ..." part of the cookie is invalid.". – PhistucK Aug 04 '14 at 09:32
3

I had a need to do this today for a SharePoint site which uses Forms Based Authentication (FBA). If you try and call an application page without cloning the cookies and assigning a CookieContainer object then the request will fail.

I chose to abstract the job to this handy extension method:

public static CookieContainer GetCookieContainer(this System.Web.HttpRequest SourceHttpRequest, System.Net.HttpWebRequest TargetHttpWebRequest)
    {
        System.Web.HttpCookieCollection sourceCookies = SourceHttpRequest.Cookies;
        if (sourceCookies.Count == 0)
            return null;
        else
        {
            CookieContainer cookieContainer = new CookieContainer();
            for (int i = 0; i < sourceCookies.Count; i++)                
            {
                System.Web.HttpCookie cSource = sourceCookies[i];
                Cookie cookieTarget = new Cookie() { Domain = TargetHttpWebRequest.RequestUri.Host, 
                                                     Name = cSource.Name, 
                                                     Path = cSource.Path, 
                                                     Secure = cSource.Secure, 
                                                     Value = cSource.Value };
                cookieContainer.Add(cookieTarget);
            }
            return cookieContainer;
        }
    }

You can then just call it from any HttpRequest object with a target HttpWebRequest object as a parameter, for example:

HttpWebRequest request;                
request = (HttpWebRequest)WebRequest.Create(TargetUrl);
request.Method = "GET";
request.Credentials = CredentialCache.DefaultCredentials;
request.CookieContainer = SourceRequest.GetCookieContainer(request);                
request.BeginGetResponse(null, null);

where TargetUrl is the Url of the page I am after and SourceRequest is the HttpRequest of the page I am on currently, retrieved via Page.Request.

Colin Gardner
  • 531
  • 5
  • 5
2

The suggested from David is the right one. You need to copy. Just simply create function to copy repeatedly. HttpCookie and Cookie object is created to make sure we can differentiate both in its functionality and where it come. HttpCookie used between user and your proxy Cookie is used between your proxy and remote web server.

HttpCookie has less functionality since the cookie is originated from you and you know how to handle it. Cookie provide you to manage cookie received from web server. Like CookieContainer, it can be used to manage domain, path and expiry.

So user side and web server side is different and to connect it, sure you need to convert it. In your case, it just simply direct assignment.

Notice that CookieContainer has a bug on .Add(Cookie) and .GetCookies(uri) method.

See the details and fix here:

http://dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html

CallMeLaNN

CallMeLaNN
  • 8,328
  • 7
  • 59
  • 74
  • Thanks for the explanation about CookieContainer's mishandling of subdomains. That bug would have had me chasing my tail when it broke in Production. – Suncat2000 Dec 24 '20 at 16:13