2012-12-02 13 views
10

prega di consultare il codice qui sotto:Come ottenere informazioni sui cookie all'interno di un CookieContainer? (Tutti, non per uno specifico dominio)

CookieContainer cookieJar = new CookieContainer(); 
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.google.com"); 
request.CookieContainer = cookieJar; 

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
int cookieCount = cookieJar.Count; 

Come posso ottenere i cookie informazioni all'interno cookieJar? (Tutti, non solo per un dominio specifico.)
E come posso aggiungere o rimuovere un cookie da quello?

risposta

13

riflessione può essere utilizzato per ottenere il campo privato che contiene tutta la chiave di dominio in oggetto CookieContainer,

D. Come ho ottenuto il nome di quel campo privato?

Ans. Utilizzando Reflector;

sua è dichiarato come:

private Hashtable m_domainTable; 

una volta che otteniamo il campo privato, avremo la chiave del dominio, quindi ottenere i cookie è un semplice iterazione.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Net; 
using System.Collections; 

namespace ConsoleApplication4 
{ 


    static class Program 
    { 

     private static void Main() 
     { 

      CookieContainer cookies = new CookieContainer(); 
      cookies.Add(new Cookie("name1", "value1", "/", "domain1.com")); 
      cookies.Add(new Cookie("name2", "value2", "/", "domain2.com")); 

      Hashtable table = (Hashtable) cookies.GetType().InvokeMember("m_domainTable", 
                     BindingFlags.NonPublic | 
                     BindingFlags.GetField | 
                     BindingFlags.Instance, 
                     null, 
                     cookies, 
                     new object[] { }); 



      foreach (var key in table.Keys) 
      { 
       foreach (Cookie cookie in cookies.GetCookies(new Uri(string.Format("http://{0}/", key)))) 
       { 
        Console.WriteLine("Name = {0} ; Value = {1} ; Domain = {2}", cookie.Name, cookie.Value, 
             cookie.Domain); 
       } 
      } 


      Console.Read(); 
     } 

    } 

} 
+0

Questo metodo sembra assumere il protocollo http e i cookie creati per https non verranno visualizzati. – user1713059

+0

@ user1713059 - dove mostra che lo sta facendo solo per HTTP? comunque, questo otterrà i cookie sia per http + https. –

+0

C'è un 'string.Format (" http: // 'nel ciclo di stampa della console.Il metodo' GetCookies' viene chiamato usando i nomi di dominio con prefisso solo http. – user1713059

1

Se si dovesse scrivere un test NUnit, sarebbe qualcosa di simile:

[Test] 
    public void Test() 
    { 

     CookieContainer cookies = new CookieContainer(); 
     cookies.Add(new Cookie("name1", "value1", "/", "www.domain1.com")); 
     cookies.Add(new Cookie("name2", "value2", "/", "www.domain2.com")); 

     Hashtable table = (Hashtable)cookies.GetType().InvokeMember("m_domainTable", 
                    BindingFlags.NonPublic | 
                    BindingFlags.GetField | 
                    BindingFlags.Instance, 
                    null, 
                    cookies, 
                    new object[] { }); 



     foreach (var key in table.Keys) 
     { 
      foreach (Cookie cookie in cookies.GetCookies(new Uri(string.Format("http://{0}/", key.ToString().Substring(1,key.ToString().Length - 1))))) 
      { 
       Assert.That(cookie != null); 
       //Console.WriteLine("Name = {0} ; Value = {1} ; Domain = {2}", cookie.Name, cookie.Value, 
       //     cookie.Domain); 
      } 
     } 



    } 
+0

Si prega di prestare attenzione alle modifiche sui domini e il secondo foreach dichiarazione –

5

di Grazie a AppDeveloper per la loro risposta, qui è una versione leggermente modificata come un metodo di estensione.

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Reflection; 
using System.Text; 

public static class CookieContainerExtension 
{ 
    public static List<Cookie> List(this CookieContainer container) 
    { 
     var cookies = new List<Cookie>(); 

     var table = (Hashtable)container.GetType().InvokeMember("m_domainTable", 
                   BindingFlags.NonPublic | 
                   BindingFlags.GetField | 
                   BindingFlags.Instance, 
                   null, 
                   container, 
                   new object[] { }); 

     foreach (var key in table.Keys) 
     { 

      Uri uri = null; 

      var domain = key as string; 

      if (domain == null) 
       continue; 

      if (domain.StartsWith(".")) 
       domain = domain.Substring(1); 

      var address = string.Format("http://{0}/", domain); 

      if (Uri.TryCreate(address, UriKind.RelativeOrAbsolute, out uri) == false) 
       continue; 

      foreach (Cookie cookie in container.GetCookies(uri)) 
      { 
       cookies.Add(cookie); 
      } 
     } 

     return cookies; 
    } 
} 

per ottenere l'elenco basta chiamare List() sul CookieContainer:

CookieContainer cookies = new CookieContainer(); 
cookies.Add(new Cookie("name1", "value1", "/", "www.domain1.com")); 
cookies.Add(new Cookie("name2", "value2", "/", "www.domain2.com")); 
List<Cookie> cookieList = cookies.List(); 
+2

Si potrebbe voler inserire l'istruzione return nel proprio metodo al di fuori del ciclo foreach – PixelZerg

3

Versione migliorata del codice di Parimal RaJ. Questo stamperà entrambi i cookie http e https. Pronto per incollarlo nella tua classe.

// Paste this dependencies in your class 
    using System; 
    using System.Net; 
    using System.Linq; 
    using System.Reflection; 
    using System.Collections; 
    using System.Collections.Generic; 

    /// <summary> 
    /// It prints all cookies in a CookieContainer. Only for testing. 
    /// </summary> 
    /// <param name="cookieJar">A cookie container</param> 
    public void PrintCookies (CookieContainer cookieJar) 
    { 
     try 
     { 
      Hashtable table = (Hashtable) cookieJar 
       .GetType().InvokeMember("m_domainTable", 
       BindingFlags.NonPublic | 
       BindingFlags.GetField | 
       BindingFlags.Instance, 
       null, 
       cookieJar, 
       new object[] {}); 


      foreach (var key in table.Keys) 
      { 
       // Look for http cookies. 
       if (cookieJar.GetCookies(
        new Uri(string.Format("http://{0}/", key))).Count > 0) 
       { 
        Console.WriteLine(cookieJar.Count+" HTTP COOKIES FOUND:"); 
        Console.WriteLine("----------------------------------"); 
        foreach (Cookie cookie in cookieJar.GetCookies(
         new Uri(string.Format("http://{0}/", key)))) 
        { 
         Console.WriteLine(
          "Name = {0} ; Value = {1} ; Domain = {2}", 
          cookie.Name, cookie.Value,cookie.Domain); 
        } 
       } 

       // Look for https cookies 
       if (cookieJar.GetCookies(
        new Uri(string.Format("https://{0}/", key))).Count > 0) 
       { 
        Console.WriteLine(cookieJar.Count+" HTTPS COOKIES FOUND:"); 
        Console.WriteLine("----------------------------------"); 
        foreach (Cookie cookie in cookieJar.GetCookies(
         new Uri(string.Format("https://{0}/", key)))) 
        { 
         Console.WriteLine(
          "Name = {0} ; Value = {1} ; Domain = {2}", 
          cookie.Name, cookie.Value,cookie.Domain); 
        } 
       } 
      } 
     } 
     catch(Exception e) 
     { 
      Console.WriteLine (e); 
     } 
    } 
+1

Grazie, il codice funziona, ma a volte ottengo errori UriFormatException. Qualche suggerimento su come ottenere quei cookie da stampare? –