为什么从手动实例化的对象(而不是当前的HttpContext)调用HttpCookieCollection.Get会返回null?

8
HttpCookieCollection.Get MSDN 文档 中,它说道:

如果指定名称的 cookie 不存在,该方法将创建一个新的 cookie,并使用该名称。

当从“真实”Web服务器调用 HttpContext.Request.CookiesHttpContext.Response.Cookies 时,这是正确的,并且可以正常工作。

然而,以下代码:

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

显示Falsecookie为空)。

如果从HTTP处理程序中的Request.Cookies检索HttpCookieCollection,则情况并非如此。

是否有任何问题/需要其他设置?

我问这个问题是因为我编写单元测试,而我模拟了HttpContextBase,因此没有提供“真实”的上下文。

感谢您的帮助。

1个回答

10

如果你查看 HttpCookieCollection.Get(string) 的代码,你会看到类似于以下内容:

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将为空(请查看第一个“if”语句),因此它从未创建cookie。也就是说,没有响应对象将新cookie返回,因此不会创建它。

响应对象是HttpResponse对象,并通过内部构造函数传递(因此该构造函数对您不可用)。

我个人从来不喜欢Get方法在HttpCookieCollection上的操作方式;它违反了命令-查询分离原则:提问不应更改答案。

我建议您通过检查AllKeys属性来检查cookie是否存在;如果不存在,请明确创建并将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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接