2013-05-06 1 views
7

В HttpCookieCollection.Get MSDN documentation, говорится, что:Почему HttpCookieCollection.Get возвращает нуль при вызове из вручную реализованным объекта (а не от текущего HttpContext)

Если названный куки не существует, этот метод создает новый файл cookie с этим именем.

Это верно и хорошо работает при вызове HttpContext.Request.Cookies или HttpContext.Response.Cookies от «реального» веб-сервера.

Однако этот код:

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

Отображение False (cookie является нулевым).

Это не тот случай, если HttpCookieCollection извлекается из Request.Cookies в обработчике HTTP.

Любая идея о том, что здесь не так, или если какая-либо другая установка необходима?

Я спрашиваю об этом, потому что я пишу модульные тесты, где я издеваюсь над HttpContextBase, поэтому никакого «реального» контекста не предусмотрено.

Спасибо за вашу помощь

ответ

8

Если вы посмотрите на код для HttpCookieCollection.Get (строки), вы увидите что-то вроде этого:

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

Он никогда не создавая печенье, потому что _response является будет иметь значение null (посмотрите на первый оператор «if»). т. е. нет объекта ответа для отправки нового файла cookie, поэтому он не будет его создавать.

Объект ответа является объектом HttpResponse и передается внутреннему конструктору (так что конструктор недоступен для вас).

Мне лично никогда не нравилось, как метод Get действует на HttpCookieCollection; он нарушает принцип Command-Query separation: задание вопроса не должно изменять ответ.

Я бы порекомендовал вам проверить наличие cookie, проверив свойство AllKeys; если он не существует, явным образом создаю и добавляю cookie в коллекцию. В противном случае, если вы знаете, что ключ существует, продолжайте и выберите существующую запись. Тогда ваш производственный код и модульные тесты должны вести себя.

Это может быть хорошая идея, чтобы создать вспомогательный или метод расширения для использования вместо Get, чтобы убедиться, что он ведет себя, как вы ожидаете ли вы модульное тестирование или работают в нормальном режиме:

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; 
    } 
} 
Смежные вопросы