2013-05-06 16 views
7

Nel HttpCookieCollection.Get MSDN documentation, si precisa che:Perché HttpCookieCollection.Get restituisce null quando chiamato da un oggetto istanziato manualmente (e non dal HttpContext corrente)

Se il cookie di nome non esiste, questo metodo crea un nuovo cookie con quel nome.

Questo è vero e funziona bene quando si chiama HttpContext.Request.Cookies o HttpContext.Response.Cookies da un server Web "reale".

Tuttavia, questo codice:

HttpCookieCollection foo = new HttpCookieCollection(); 
    HttpCookie cookie = foo.Get("foo"); 
    Console.WriteLine(cookie != null); 

Displays False (cookie IS NULL).

Questo non è il caso se il numero HttpCookieCollection viene recuperato da Request.Cookies in un gestore HTTP.

Qualche idea di cosa c'è che non va qui/se sono necessarie altre impostazioni?

Lo sto chiedendo perché scrivo test di unità in cui mi faccio beffe di HttpContextBase, quindi non viene fornito alcun contesto "reale".

Grazie per il vostro aiuto

risposta

8

Se si guarda il codice per HttpCookieCollection.Get (stringa), vedrete qualcosa di simile:

public HttpCookie Get(string name) 
{ 
    HttpCookie cookie = (HttpCookie) this.BaseGet(name); 
    if (cookie == null && this._response != null) 
    { 
    cookie = new HttpCookie(name); 
    this.AddCookie(cookie, true); 
    this._response.OnCookieAdd(cookie); 
    } 
    if (cookie != null) 
    this.EnsureKeyValidated(name, cookie.Value); 
    return cookie; 
} 

Non è mai creare il cookie perché _response è sta per essere nullo (guarda la prima dichiarazione "se"). non c'è nessun oggetto risposta a cui inviare il nuovo cookie, quindi non lo creerà.

L'oggetto risposta è un oggetto HttpResponse ed è passato al costruttore interno (in modo che il costruttore non sia disponibile).

Personalmente non mi è mai piaciuto il modo in cui il metodo Get agisce su HttpCookieCollection; viola il principio Command-Query separation: fare una domanda non dovrebbe cambiare la risposta.

Si consiglia di verificare l'esistenza del cookie controllando la proprietà AllKeys; se non esiste, crea e aggiunge esplicitamente il cookie alla raccolta. Altrimenti, se sai che la chiave esiste, vai avanti e recupera la voce esistente. Quindi il codice di produzione e i test di unità dovrebbero comportarsi.

Potrebbe essere una buona idea per creare un metodo di supporto o estensione da usare al posto di Get, al fine di garantire si comporta come ci si aspetta che tu sia il test delle unità o in esecuzione normalmente:

public static class HttpCookieCollectionExtensions 
{ 
    public static HttpCookie GetOrCreateCookie(this HttpCookieCollection collection, string name) 
    { 
     // Check if the key exists in the cookie collection. We check manually so that the Get 
     // method doesn't implicitly add the cookie for us if it's not found. 
     var keyExists = collection.AllKeys.Any(key => string.Equals(name, key, StringComparison.OrdinalIgnoreCase)); 

     if (keyExists) return collection.Get(name); 

     // The cookie doesn't exist, so add it to the collection. 
     var cookie = new HttpCookie(name); 
     collection.Add(cookie); 
     return cookie; 
    } 
} 
Problemi correlati