眾所周知,Session是運行在伺服器端的,JavaScript是運行在用戶端的,JavaScript不能直接運行伺服器端的代碼。但最近筆者卻遇到了這樣的需求:在一個學習系統裡面,使用者不能同時開啟兩個線上考試或線上學習的視窗。通過開啟模態對話方塊,的確可以禁止使用者再開啟一個新視窗,但如果使用者重新開啟一個新的頁面,卻可以開啟一個新的對話方塊。
於是便想到了使用Cookies和Session記錄使用者開啟考試或學習視窗,因為Cookies和Session都有全域作用。但Cookies有個缺點就是,如果使用者清空了Cookies,則Cookies值便會丟失,於是便剩下使用Session了。但有個比較棘手的問題是,如果使用者直接按瀏覽器的關閉按鈕退出視窗怎麼辦?因為這樣根本就不會執行背景代碼。於是便很容易想到了使用Ajax請求的方式。如下面代碼:
在線上學習頁面的cs檔案中判斷是否已經開啟學習頁面
1 if (Session["study"]==null || Session["study"]=="")
2 {
3 Session["study"] = "true";
4 }
5 else
6 {
7 string myScript = @"alert('你已經開啟一個線上學習視窗,不能同時開啟多個線上學習視窗!'); type = 1; window.close(); ";
8 Page.ClientScript.RegisterStartupScript(this.GetType(), "MyScript", myScript, true);
9 }
注意,這裡註冊了一段JavaScript,並且調用了window.close()方法,這種情況下關閉頁面是不能清空Session[“study”]的值的。所以加了一個type=1,如果是type==1,則不清空Session值。而前台也聲明了一個type=0,當type==0表示是使用者直接關閉視窗,是需要清空Session值。
1 function window.onbeforeunload() {
2 if (type == 0) {
3 var xmlHttp = createXMLHttpRequest();
4 xmlHttp.open('GET', "EndStudy.aspx", true);
5 xmlHttp.send(null);
6 xmlHttp.onreadystatechange = function() {
7 if (4 == xmlHttp.readyState) {
8 if (200 == xmlHttp.status) {
9 }
10 else {
11 }
12 }
13 }
14 }
15 }
在EndStudy.aspx.cs中清除Session的值
1 protected void Page_Load(object sender, EventArgs e)
2 {
3 Session["study"] = "";
4 }
貌似這種方法沒有什麼問題。如果在關閉視窗前,請求頁面清除了Session的值,的確可以實現需求。但我卻為此鬱悶了很久,發現第一次關閉頁面清除Sesson值成功,第二次關閉頁面時,請求EndStudy.aspx成功,去沒有執行EndStudy.aspx.cs中的Page_Load函數。所以想再次開啟線上學習頁面,卻提示不能“同時開啟兩個線上學習視窗”。
後來想到對話方塊是有緩衝的,於是便在線上學習頁面和它的承載頁面的Page_Load執行了清除Session的代碼:
1 Response.Buffer = true;
2 Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1);
3 Response.Expires = 0;
4 Response.CacheControl = "no-cache";
5 Response.AddHeader("Pragma", "No-Cache");
但問題依舊,最後在EndStudy.aspx.cs的Page_Load也加了清除Session的代碼才解決問題。
EndStudy.aspx.cs中的Page_Load最終代碼如下:
1 protected void Page_Load(object sender, EventArgs e)
2 {
3 Response.Buffer = true;
4 Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1);
5 Response.Expires = 0;
6 Response.CacheControl = "no-cache";
7 Response.AddHeader("Pragma", "No-Cache");
8
9 Session["study"] = "";
10 }