检查Cookie是否存在。

61

Stack Overflow上进行快速搜索后,我看到有人建议使用以下方式来检查cookie是否存在:

HttpContext.Current.Response.Cookies["cookie_name"] != null

或者(在Page类内部):
this.Response.Cookies["cookie_name"] != null

然而,当我尝试使用索引器(或Cookies.Get方法)检索不存在的cookie时,它似乎实际上会创建一个具有该名称的“默认”cookie并返回它,因此无论我使用什么cookie名称都不会返回null。(更糟糕的是 - 创建了一个不需要的cookie)
我在这里做错了什么,还是有其他简单检查特定cookie存在的方法?
7个回答

65
有时,您仍然需要知道响应中是否存在 Cookie。然后,您可以检查 cookie 键是否存在:
HttpContext.Current.Response.Cookies.AllKeys.Contains("myCookie")

在这里可以找到更多信息:http://blog.mastykarz.nl/inconvenient-asp-net-cookies/
在我的情况下,我需要在 Global.asax 的 Application_EndRequest 方法中修改 Response Cookie。如果 Cookie 不存在,则不会触及它。
string name = "myCookie";
HttpContext context = ((HttpApplication)sender).Context;
HttpCookie cookie = null;

if (context.Response.Cookies.AllKeys.Contains(name))
{
    cookie = context.Response.Cookies[name];
}

if (cookie != null)
{
    // update response cookie
}

2
如果您需要检查响应中生成的 cookie,则这是正确的答案。 - gxclarke
3
如果你的AllKeys集合中没有包含Contains函数,你可以引入LINQ来实现(using System.Linq)。 - palswim
这个第一个条件语句中的 sender 是什么?它在我的控制器方法中显示错误。 - Rajan Mishra
你应该使用 Request 而不是 Response。 - Wessam El Mahdy

59

根据您的目标,有很多正确的答案; 这是我提供全面答案的尝试:

RequestResponse对象都包含Cookies属性,这些属性是HttpCookieCollection对象。

Request.Cookies:

  • 此集合包含从客户端接收到的cookie
  • 该集合是只读的
  • 如果你尝试访问一个不存在的cookie,你会收到一个null

Response.Cookies:

  • 这个集合只包含在当前请求期间由服务器添加的cookie。
  • 该集合是可写的
  • 如果你尝试访问一个不存在的cookie,你将收到一个新的cookie对象;如果你尝试访问的cookie在Request.Cookies集合中不存在,它将被添加(但如果Request.Cookies对象已经包含具有相同键的cookie,即使它的值已过时,它也不会更新以反映Response.Cookies集合中新创建的cookie的更改)

解决方案


如果您想检查客户端是否存在cookie,请执行以下操作之一

  • Request.Cookies["COOKIE_KEY"] != null
  • Request.Cookies.Get("COOKIE_KEY") != null
  • Request.Cookies.AllKeys.Contains("COOKIE_KEY")

如果您想检查在当前请求期间由服务器添加的cookie是否存在,请执行以下操作:

  • Response.Cookies.AllKeys.Contains("COOKIE_KEY")(请参见此处)

尝试通过以下方法之一检查由服务器在当前请求期间添加的 cookie:

  • Response.Cookies["COOKIE_KEY"] != null
  • Response.Cookies.Get("COOKIE_KEY") != null (查看 这里)

这样做将在 Response.Cookies 集合中创建一个 cookie,状态将评估为 true


1
感谢这个总结。 - Donnelle
1
这是一个很好的总结,也符合我所看到的行为。最后关于响应的部分 - 索引器、获取器和列表 - 有没有文档记录?他们可能会更改该行为,导致我们的代码失败。 - h bob
我找到了有关调用 Response.Cookies.Get("COOKIE_KEY") 的文档,并更新了答案,附上了链接。对于 Response.Cookies.Item[String] 的文档并没有提到创建新 cookie 的任何内容,但是我认为在底层它很有可能只是在调用 Response.Cookies.Get(String)Response.Cookies.AllKeys.Contains(String) 的文档也没有特别提到这种行为,但我怀疑这是因为 AllKeys 只是所有现有 cookie 的 String[],而 Contains(String) 方法因此在另一个库中实现。 - Trevor

44

Response.Cookies 包含将发送回浏览器的 cookie。如果想要知道某个 cookie 是否存在,您可能应该查看 Request.Cookies

无论如何,要查看 cookie 是否存在,可以检查 Cookies.Get(string)但是,如果您在 Response 对象上使用此方法并且 cookie 不存在,则会创建该 cookie。

请参阅 MSDN 参考中的 HttpCookieCollection.Get 方法(字符串)


3
使用 Request 而不是 Response 似乎可以按照我的期望工作。谢谢(两个答案基本相同,但你回答得更快)。 - Acidic
16
在链接文档中,有关Cookies.Get(string)的备注指出:“如果指定名称的cookie不存在,则此方法会创建一个新的具有该名称的cookie。” - Michael Petito
2
@MichaelPetito 虽然文档上是这么说的,但我发现如果找不到它会返回 null。我认为只有在处理响应时才适用于“如果不存在则创建”。如果 Request.Cookies 为空,则 Get 返回 null。你现在可以看到一些用户对此文档的评论。 - AaronLS
4
为什么要假设OP不想知道响应cookie是否存在?也许他们想知道是否已经将cookie添加到响应中。在问题的背景下,使用"Get"方法无法实现。 - xr280xr
1
Aaron,无论文档怎么说... get方法的代码如下: HttpCookie cookie = (HttpCookie) this.BaseGet(name);
if (cookie == null && this._response != null)
{
cookie = new HttpCookie(name);
this.AddCookie(cookie, true); [...] 显然新的cookie将被返回,所以就检查请求而言,我不会依赖于集合行为。
- mikus
显示剩余3条评论

36
你需要使用HttpContext.Current.Request.Cookies,而不是Response.Cookies
顺便说一下:cookie在Response.Cookies.Add时被复制到Request中,这使得对于新添加的cookie来说,无论在哪个集合中检查都会表现出相同的行为。但是,传入的cookie永远不会反映在Response中。
这种行为在HttpResponse.Cookies属性中有记录:

使用HttpResponse.Cookies集合添加cookie后,即使尚未将响应发送到客户端,该cookie也会立即在HttpRequest.Cookies集合中可用。


谢谢,使用“Request”基本上就是我所需要的。+1 - Acidic
这是我找到的唯一关于那个Cookie复制行为的文档 - 谢谢!它真的很讨厌。 - Evan M
7
是的,关于这个“附注”,复制只会发生在新的cookies上。如果您更新响应中的cookie,则不会更新请求中已经存在的cookie。如果您的框架在同一次请求中多次修改cookie,则可能会导致麻烦。 - AaronLS

4
public static class CookieHelper
{
    /// <summary>
    /// Checks whether a cookie exists.
    /// </summary>
    /// <param name="cookieCollection">A CookieCollection, such as Response.Cookies.</param>
    /// <param name="name">The cookie name to delete.</param>
    /// <returns>A bool indicating whether a cookie exists.</returns>
    public static bool Exists(this HttpCookieCollection cookieCollection, string name)
    {
        if (cookieCollection == null)
        {
            throw new ArgumentNullException("cookieCollection");
        }

        return cookieCollection[name] != null;
    }
}

使用方法:

Request.Cookies.Exists("MyCookie")

我在Cookie类中找不到Exists方法。 - Imad
1
这段代码创建了一个扩展到Cookie类的方法,它添加了“Exists”方法。扩展真的很酷。 - CigarDoug
2
尽管如此,[] 操作符的代码调用 Get 方法,如果没有找到 Cookie,则会创建一个新的 Cookie,这意味着结果永远不会为 null,只是一个空的 Cookie(在 HttpResponse 的情况下)。 - mikus
2
根据最后一条评论,你的返回语句应该是 return cookieCollection.AllKeys.Contains(name); - Chris Walsh

2

抱歉,声望值不足无法添加评论,但从zmbq的答案可以看出:

无论如何,要查看cookie是否存在,您可以检查Cookies.Get(string),这不会修改cookie集合。

可能并不完全正确,因为Cookies.Get(string)实际上会创建具有该名称的cookie(如果不存在)。然而,正如他所说,您需要查看Request.Cookies,而不是Response.Cookies。因此,类似于以下内容:

bool cookieExists = HttpContext.Current.Request.Cookies["cookie_name"] != null;

这是不正确的,它会返回 null: "Cookies.Get(string) 实际上会创建一个具有该名称的 cookie"。 - AaronLS
1
我后来了解到,当使用Response.Cookies时,create if not exists适用,但在使用Request.Cookies时不适用。 - AaronLS

0
你可以像这样做,以查找cookie的值:
Request.Cookies[SESSION_COOKIE_NAME].Value

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