2009-11-21 5 views
26

Ho un CookieContainer estratto da un HttpWebRequest/HttpWebResponse sessione di nome Cookiejar. Voglio che la mia applicazione memorizzi i cookie tra le esecuzioni, quindi i cookie raccolti nello CookieContainer in una sessione del programma verranno utilizzati anche nella prossima esecuzione.C#: Scrivi CookieContainer su disco e caricamento di Back In Per l'uso

Penso che il modo per farlo sarebbe in qualche modo scrivere su disco il contenuto di un CookieContainer. La mia domanda è:

  • Come si fa a scrivere un CookieContainer al disco? Esistono funzioni integrate per questo o, in caso contrario, quali sono gli approcci che le persone hanno adottato? Ci sono delle classi disponibili per semplificare questo?
  • Dopo aver scritto un CookieContainer sul disco, come lo si può caricare per l'uso?

UPDATE: La prima risposta ha suggerito serializzazione del CookieContainer. Tuttavia, non ho molta familiarità con la serializzazione e la deserializzazione di oggetti così complessi. Potresti fornire un codice di esempio ? Il suggerimento era di utilizzare SOAPFormatter.

risposta

19

Non l'ho provato ma ha l'attributo Serializable e così può essere [de] serializzato con la serializzazione binaria .net, ad es. SoapFormatter.

Ecco lo snippet di codice che hai richiesto.

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); 

Guardando MSDN sembra SoapFormatter è ormai obsoleta in .NET 3.5 e raccomanda di utilizzare BinaryFormatter. In passato ho trovato SoapFormatter utile in quanto il file è leggibile e aiuta nella diagnosi quando la deserializzazione fallisce! Questi formattatori sono sensibili alle modifiche della versione anche nella versione di assemblaggio (quindi se si deserializza con una versione del framework si aggiorna il framework, quindi non si può deserializzare, non è sicuro), ma ci sono modi per aggirare questo con la proprietà Binder se questo diventa un problema. Credo che siano progettati principalmente per persistenza/remoting a breve termine, ma potrebbero essere abbastanza buoni per voi qui.

Il nuovo DataContractSerializer sembra non funzionare correttamente.

Un'alternativa sarebbe scrivere una classe CookieContainerData per [de] serializzare con XmlSerializer e convertire manualmente tra questo e CookieContainer.

+0

Non so molto sulla serializzazione, quindi potresti fornire qualche codice di esempio? –

+2

codice di esempio aggiunto –

27

Questo problema mi dava fastidio per anni, niente di quello che riuscivo a trovare funzionava. L'ho risolto, quindi ho messo queste informazioni nel mondo.

risposta utilizzando 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

C'è comunque che posso memorizzare in SQL invece di un file? – juanora

0

Un'altra alternativa è quella di utilizzare serializzazione JSON (Json.NET):

// other includes 
using Newtonsoft.Json; 

Una classe con un biscotto:

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

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

Ecco come serializzarlo 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

Il problema è serializzare l'oggetto CookieContainer, non l'oggetto Cookie. – Zax

Problemi correlati