2009-11-21 16 views
26

Tengo una CookieContainer extraído de una sesión de HttpWebRequest/HttpWebResponse llamado CookieJar. Quiero que mi aplicación almacene cookies entre ejecuciones, por lo que las cookies recopiladas en el CookieContainer en una ejecución del programa también se usarán en la próxima ejecución.C#: Escribir un CookieContainer en disco y carga de nuevo en Para uso

Creo que la forma de hacerlo sería escribir de alguna manera el contenido de un CookieContainer en el disco. Mi pregunta es:

  • Cómo se puede escribir una CookieContainer al disco? ¿Hay funciones incorporadas para esto, o, si no, cuáles son los enfoques que las personas han tomado? ¿Hay alguna clase disponible para simplificar esto?
  • Una vez que haya escrito un CookieContainer en el disco, , ¿cómo lo vuelve a cargar para usar?

ACTUALIZACIÓN: La primera respuesta ha sugerido serialización del CookieContainer. Sin embargo, no estoy muy familiarizado con la forma de serializar y deserializar tales objetos complejos. ¿Podría proporcionar un código de ejemplo ? La sugerencia fue utilizar SOAPFormatter.

Respuesta

19

No lo he probado pero tiene el atributo Serializable y, por lo tanto, puede [de] serializarse con serialización binaria .net, p. SoapFormatter.

Aquí está el fragmento de código que solicitó.

var formatter = new SoapFormatter(); 
string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cookies.dat"); 

using (Stream s = File.Create (file)) 
    formatter.Serialize(s, cookies);        
... 
CookieContainer retrievedCookies = null; 
using (Stream s = File.OpenRead (file)) 
    retrievedCookies = (CookieContainer) formatter.Deserialize(s); 

En cuanto a MSDN parece SoapFormatter ahora es obsoleto en .NET 3.5 y se recomienda que utilice BinaryFormatter. En el pasado, he encontrado que SoapFormatter es útil ya que el archivo es legible, lo que ayuda al diagnóstico cuando falla la deserialización. Estos formateadores son sensibles a los cambios de versión incluso en la versión de ensamblaje (por lo que si deserializa con una versión del marco, actualice el marco, entonces puede que no se deserialice, no está seguro), pero hay formas de evitar esto con la propiedad Binder. un problema. Creo que están diseñados principalmente para la persistencia/interacción a corto plazo, pero podrían ser lo suficientemente buenos para ti aquí.

Parece que el nuevo DataContractSerializer no funciona, por lo que está apagado.

Una alternativa sería escribir una clase CookieContainerData para [de] serializar con XmlSerializer y convertir manualmente esto y CookieContainer.

+0

No sé demasiado sobre la serialización, ¿podría proporcionarnos algún código de muestra? –

+2

código de ejemplo agregado –

27

Este problema me estaba molestando durante años, nada de lo que pude encontrar funcionó. Lo resolví, así que sacando esa información al mundo.

respuesta utilizando BinaryFormatter:

public static void WriteCookiesToDisk(string file, CookieContainer cookieJar) 
    { 
     using(Stream stream = File.Create(file)) 
     { 
      try { 
       Console.Out.Write("Writing cookies to disk... "); 
       BinaryFormatter formatter = new BinaryFormatter(); 
       formatter.Serialize(stream, cookieJar); 
       Console.Out.WriteLine("Done."); 
      } catch(Exception e) { 
       Console.Out.WriteLine("Problem writing cookies to disk: " + e.GetType()); 
      } 
     } 
    } 

    public static CookieContainer ReadCookiesFromDisk(string file) 
    { 

     try { 
      using(Stream stream = File.Open(file, FileMode.Open)) 
      { 
       Console.Out.Write("Reading cookies from disk... "); 
       BinaryFormatter formatter = new BinaryFormatter(); 
       Console.Out.WriteLine("Done."); 
       return (CookieContainer)formatter.Deserialize(stream); 
      } 
     } catch(Exception e) { 
      Console.Out.WriteLine("Problem reading cookies from disk: " + e.GetType()); 
      return new CookieContainer(); 
     } 
    } 
+0

De todos modos, ¿puedo almacenar en SQL en lugar de un archivo? – juanora

0

Otra alternativa es utilizar la serialización JSON (Json.NET):

// other includes 
using Newtonsoft.Json; 

Una clase con una galleta:

public class WithCookie 
{ 
    public Cookie MyCookie { get; set; } 

    public WithCookie() 
    { 
     MyCookie = new Cookie("CF788DF", "A cookie value!", "/", ".test.com"); 
    } 
} 

Aquí es cómo serializarlo a Json:

class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      WithCookie wc1 = new WithCookie(); 
      // Expires a month from now 
      wc1.MyCookie.Expires = DateTime.Now.AddMonths(1); 

      string wc1json = JsonConvert.SerializeObject(new WithCookie()); 

      WithCookie wc2 = JsonConvert.DeserializeObject < WithCookie>(wc1json); 

      string wc2json = JsonConvert.SerializeObject(wc2); 

      if (wc2json == wc1json) 
      { 
       Console.WriteLine("HORRAY!"); 
      } 
      else 
      { 
       // The strings will not be equal, because the Cookie.TimeStamp 
       // changes but the cookies are in fact the same! 
       Console.WriteLine("FAIL!"); 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Exception: " + e.ToString()); 
     } 
     Console.ReadKey(); 
    } 
} 
+4

El problema es serializar el objeto CookieContainer, no el objeto Cookie. – Zax

Cuestiones relacionadas