Sending cookies using HttpCookieCollection and CookieContainer
Asked Answered
R

3

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?

Rye answered 31/7, 2009 at 19:23 Comment(0)
M
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 );
}
Miceli answered 31/7, 2009 at 19:30 Comment(6)
I think this technique will work, but I was really hoping for a solution that wouldn't involve copying each value over.Rye
whats with the try with the empty catch?Decontrol
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. @MiceliAcetate
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?Katz
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.Ganister
An exception is thrown due to encoding issues. "The "Value = ..." part of the cookie is invalid.".Chekhov
M
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.

Mum answered 28/5, 2013 at 0:46 Comment(0)
D
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

Disbursement answered 8/10, 2009 at 14:6 Comment(1)
Thanks for the explanation about CookieContainer's mishandling of subdomains. That bug would have had me chasing my tail when it broke in Production.Couch

© 2022 - 2024 — McMap. All rights reserved.