[ASP.net] Cookie怎麼寫就怎麼讀

[ASP.net] Cookie怎麼寫就怎麼讀

最近翻閱ASP.net 問題解決[實戰] 此本書的3-89頁介紹到

若想要依使用者的選擇來動態切換Master Page的話,可以先將使用者的選擇寫到Cookie中,然後再(Page_PreInit事件)依前述(Page.MasterPageFile=網路路徑)來切換Master Page

例如:

Response.Cookies.Add("MasterPage", "~/masterPage/MyMasterPage.master");

 

以上的程式碼讓我覺得詭異的情況下,自行Try了一下,果然Cookie不是這樣寫的

image

正確寫法:

asp.net,cookie,写cookie,取cookieAsp.Net -Cookie讀取中文變亂碼的解決方法

也因為翻了幾篇文章,重新認識Cookie,剛好有空有心情

就來測試一下

1. 如果輸出HttpCookie物件的單值,讀取時卻以多值的方式讀回來,或

2. 輸出HttpCookie物件的多值,讀取時卻以單值的方式讀回來的情況會怎樣?

 

Case 1:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //產生一個Cookie
            HttpCookie cookie = new HttpCookie("test");
            //設定單值
            cookie.Value = Server.UrlEncode("Hello!!世界");
            //設定過期日
            cookie.Expires = DateTime.Now.AddDays(2);
            //寫到用戶端
            Response.Cookies.Add(cookie);

        }
    }


    //讀取cookie(以多值的方式)
    protected void btn_test_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = Request.Cookies["test"];
        foreach (string value in cookie.Values)
        {
            Response.Write("Null?"+(value==null)+"<br/>");/*順便測試看看是否為null還是空字串*/
            Response.Write("空字串?"+(value=="")+"<br/>");
            Response.Write("foreach迴圈中撈出Request.Cookies['test']所有的Value:" + Server.UrlDecode(value)+"<hr/>");
        }

        Response.Write("Null?"+(cookie["test"]==null)+"<br/>");
        Response.Write("空字串?" + (cookie["test"]=="")+"<br/>");
        Response.Write("cookie['test'](HttpCookie物件裡索引名為test的值):"+Server.UrlDecode(cookie["test"])+"<hr/>");
    }
}

執行結果:

第一次網頁執行

image

按下Button

image

以多值方式讀取回來的值都是空值null

接著我把IE9中所有的暫存和Cookie刪除

image

再改寫一下程式碼(這次讀取改以單值的方式),並重新執行按下Button


    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //產生一個Cookie
            HttpCookie cookie = new HttpCookie("test");
            //設定單值
            cookie.Value = Server.UrlEncode("Hello!!世界");
            //設定過期日
            cookie.Expires = DateTime.Now.AddDays(2);
            //寫到用戶端
            Response.Cookies.Add(cookie);

        }
    }


    //讀取cookie(這次改以單值的方式)
    protected void btn_test_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = Request.Cookies["test"];
         

        Response.Write("Null?"+(cookie.Value==null)+"<br/>");
        Response.Write("空字串?" + (cookie.Value=="")+"<br/>");
        Response.Write("顯示cookie.Value的值:" + Server.UrlDecode(cookie.Value) + "<hr/>");
    }

執行結果:

image

這次就有值了

 

Case 2 : (輸出HttpCookie物件的多值,讀取時卻以單值的方式讀回來的情況)

程式碼:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //產生一個Cookie物件
            HttpCookie cookie = new HttpCookie("test");
            //設定多值(這裡只能以字串的方式設定)
            cookie.Values.Add("1", "Hello");
            cookie.Values.Add("2", Server.UrlEncode("世界!!"));
            //設定過期日(這裡只能針對全體cookie物件設定過期日)
            cookie.Expires = DateTime.Now.AddDays(2);
            //寫到用戶端
            Response.Cookies.Add(cookie);

        }
    }


    //讀取cookie(以單值的方式)
    protected void btn_test_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = Request.Cookies["test"];
         

        Response.Write("Null?"+(cookie.Value==null)+"<br/>");
        Response.Write("空字串?" + (cookie.Value=="")+"<br/>");
        Response.Write("顯示cookie.Value的值:" + Server.UrlDecode(cookie.Value) + "<hr/>");
    }
}

一樣我事先把IE9的暫存和Cookie刪除並關閉所有IE9視窗

image

然後才執行程式:

第一次網頁執行

image

按下Button

image

所以用多值的方式寫出去,以單值的方式讀回來的Value

就會像以上的結果,是用Key=Value&Key=Value的值回傳回來(不是null)

所以多值輸出的正確讀取方式應該如下:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //產生一個Cookie物件
            HttpCookie cookie = new HttpCookie("test");
            //設定多值(這裡只能以字串的方式設定)
            cookie.Values.Add("1", "Hello");
            cookie.Values.Add("2", Server.UrlEncode("世界!!"));
            //設定過期日(這裡只能針對全體cookie物件設定過期日)
            cookie.Expires = DateTime.Now.AddDays(2);
            //寫到用戶端
            Response.Cookies.Add(cookie);

        }
    }


    //讀取cookie(改以多值的方式)
    protected void btn_test_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = Request.Cookies["test"];
         
        Response.Write("顯示cookie物件裡的值1:" + cookie.Values["1"] + "<hr/>");
        Response.Write("顯示cookie物件裡的值2:" + Server.UrlDecode(cookie.Values["2"]) + "<hr/>");
    }
}

 

2011.12.15追記 使用cookie["1"]、cookie["2"]來讀取應該也行

 

執行結果:

image

 

接下來解決幾個疑惑

HttpCookie cookie = new HttpCookie("test")
cookie.Value等於cookie["test"]???

 

答案是No~

請看程式碼:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //產生一個Cookie物件
            HttpCookie cookie = new HttpCookie("test");
            //設定單值(這裡只能以字串的方式設定)
            cookie.Value = "Hello World!!";
            //設定過期日(這裡只能針對全體cookie物件設定過期日)
            cookie.Expires = DateTime.Now.AddDays(2);
            //寫到用戶端
            Response.Cookies.Add(cookie);

        }
    }


    //嘗試讀取cookie 
    protected void btn_test_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = Request.Cookies["test"];

        Response.Write("cookie['test']為Null?" + (cookie["test"]==null) + "<hr/>");
        Response.Write("cookie['test']為空字串?:" + (cookie["test"]=="") + "<hr/>");
        Response.Write("顯示cookie['test']的值:" + cookie["test"] + "<hr/>");
        Response.Write("顯示cookie物件的單值(cookie.Value):" + cookie.Value + "<hr/>");
    }
}

 

執行結果:

第一次執行畫面

image

按下Button

image

 

所以正確應該說cookie["test"]其實就相當於Request.Cookies["test"]["test"]

請見以下代碼:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //產生一個Cookie物件
            HttpCookie cookie = new HttpCookie("test");
            //設定多值(這裡只能以字串的方式設定)
            cookie.Values.Add("test", "Hi");
            cookie.Values.Add("test2", "shadow");
            //設定過期日(這裡只能針對全體cookie物件設定過期日)
            cookie.Expires = DateTime.Now.AddDays(2);
            //寫到用戶端
            Response.Cookies.Add(cookie);

        }
    }


    //嘗試讀取cookie 
    protected void btn_test_Click(object sender, EventArgs e)
    {
        Response.Write(Request.Cookies["test"]["test"]);
         
    }
}

按下按鈕後的執行結果:

image

 

 

 

第二個問題

如果不設定過期日,預設Cookie什麼時候會過期?

我先把IE9的暫存和Cookie都刪除後,嘗試再度輸出Cookie


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
           
             
        }
    }


    
    protected void btn_test_Click(object sender, EventArgs e)
    {
        //產生一個Cookie物件
        HttpCookie cookie = new HttpCookie("test");
        //設定多值(這裡只能以字串的方式設定)
        cookie.Values.Add("test", "Hi");
        cookie.Values.Add("test2", "shadow");
        //不設定過期日 
        
        //寫到用戶端
        Response.Cookies.Add(cookie);
         
    }
}

執行:

image

按下Button寫出Cookie

image

 

但這次不做瀏覽器的清除Cookie動作我就直接關閉瀏覽器

並改寫程式碼嘗試讀取Cookie


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Response.Write("Request.Cookies['test']['test']為Null?"+(Request.Cookies["test"]["test"]==null)+"<hr/>");
            Response.Write("Request.Cookies['test']['test']為空字串?" + (Request.Cookies["test"]["test"] == "") + "<hr/>");
            Response.Write("Request.Cookies['test']['test']的值為:" + Request.Cookies["test"]["test"] + "<hr/>");
             
        }
    }


    
    protected void btn_test_Click(object sender, EventArgs e)
    {
         
         
    }
}

執行結果:

image

直接NullReferenceException,沒有Request.Cookies["test"]["test"]這東西

也就是說Cookie物件沒給過期值,預設當瀏覽器關閉後就跟著消失

请问客户端cookie默认生命周期是多长时间?

 

最後再順便看看寫出Cookie的單值和多值會以什麼形式儲存在IE9上


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //單值
            HttpCookie cookie = new HttpCookie("test");
            cookie.Value = "testValue值";
            cookie.Expires = DateTime.Now.AddDays(2);
            Response.Cookies.Add(cookie);

            //多值
            HttpCookie cookies = new HttpCookie("test2");
            cookies.Values.Add("1", "Hi");
            cookies.Values.Add("2測試", "測試值");
            cookies.Expires = DateTime.Now.AddDays(2);
            Response.Cookies.Add(cookies);
        }
    }


    
    protected void btn_test_Click(object sender, EventArgs e)
    {
         
         
    }
}

先執行程式輸出Cookie到用戶端:

image

再嘗試在瀏覽器中尋找剛剛輸出的Cookie

image

image

image

image

把此檔案打開來

image

 

 

2011.12.15 追記,剛剛試著把寫入的Cookie沒做UrlEncode、UrlDecode直接活生生地讀取出來,中文沒有變亂碼,推測應該是IE9的關係。

 

2011.12.16 追記,睡前想到要模擬一個情況

如果單值和多值都同時設定的話,會?


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class B : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
                //單值
                HttpCookie cookie = new HttpCookie("2011.12.16");
                cookie.Value = "testValue值";
                
                
                //針對同一個物件寫入多值
                cookie.Values.Add("1", "Hi");
                cookie.Values.Add("2測試", "測試值");


                cookie.Expires = DateTime.Now.AddDays(2);
                Response.Cookies.Add(cookie);
            
         
        }
    }


    //讀取Cookie,並顯示
    protected void btn_test_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = Request.Cookies["2011.12.16"];
        Response.Write("單值:"+cookie.Value+"<hr/>");
        Response.Write("以下為多值<br/>");
        Response.Write(cookie["1"] + "<br/>");
        Response.Write(cookie["2測試"] + "<br/>");
         
    }
}

按下Button後的執行結果:

image

所以還是別混著使用為妙

衍伸閱讀:[ASP.net] 透過JavaScript 建立.刪除.讀取Cookie解決方案,包含C#讀取解決中文亂碼問題..