驗證 AJAX 動態載入的頁面是否已被導向(簡單版)
- 1231
- 6
這標題還真難下,完整的說明應該是「解決需要登入的頁面用 AJAX 動態載入時很容易因為使用者閒置過久導致被導向登入畫面的問題」,很多時候在會員專屬頁面中我們還是會使用 AJAX 技術去動態載入一些頁面,正常使用情況下是非常好的使用者經驗,但是如果會員閒置過久而導致系統早就已經自動登出了,但是因為頁面並沒有重新整理所以當會員又按下某一功能時,AJAX原本要動態換掉的區塊(div)變成了登入畫面甚至於跑回首頁,這是非常非常差的使用者經驗,demo 目前有想到一個很簡單的解決方案,提出來看看有沒有人有更好的解決方式。
- 最後更新:2012/1/1 下午 08:21:45
本範例使用 VS2010 的 MVC 預設樣板,不了解 MVC 沒關係,因為只是一個框架,並不影響本文要說的主題。
先使用預設的 MVC 專案增加一個 ActionResult
public ActionResult Index()
{
ViewData["Message"] = "歡迎使用 ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult needLogin()
{
return View();
}
再來我在頁面中寫一點點 Code
<h2><%: ViewData["Message"] %></h2>
<p>
若要進一步了解 ASP.NET MVC,請造訪 <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>。
</p>
--動態載入開始<div id="j_ajax"></div>--動態載入結束
<script type="text/javascript">
$(function ()
{
$.ajax({
type: "GET",
url: '/Home/needLogin',
success: function (data)
{
$('#j_ajax').html(data);
}
});
});
</script>
觀看頁面的時候就可以看到很正常的畫面
然後將 動態載入的頁面改成需要登入
[Authorize]
public ActionResult needLogin()
{
return View();
}
再次執行首頁卻看到了
原本想說判斷狀態碼來解決這問題,因為被導向到登入頁面是屬於「301」所以我當下認為只要抓到301就表示沒登入了,但實際下去跑以後都只能抓到「200」,後來想想才覺得沒錯,因為我是正常的到達那頁面後才被導向,所以順序就的確是「200」才變「301」,因此第一個想法宣告失敗....
後來又想說既然這樣,那我就想想 AJAX 的頁面和一般頁面有什麼不同,這念頭一出來我就想到了 <HTML>這個 Tag ,正常的情況下動態載入的頁面都是片段的,不可能會擁有 <HTML> 因此我就將程式碼改寫如下。
第一次改寫後的 Code
$(function ()
{
$.ajax({
type: "GET",
url: '/Home/needLogin',
success: function (data)
{
if (data.indexOf("<html") > -1)
{
alert('您尚未登入!');
}
else
{
$('#j_ajax').html(data);
}
}
});
});
反正 data 註定是要傳回來的,所以就直接去找他就好了,而 寫 <html 的原因是有很多的時候 html 後面還會接一堆東西,因此只寫頭,這樣子寫了以後當使用者遇到需要登入才能看得頁面就會跳出 您尚未登入 的提示訊息。

第二次改寫後的 Code
問題又來了,跳出 alert 有啥用,使用者通常都不會看訊息,都是有訊息就按掉以後再來問為什麼我按了沒反應,為了終結掉這種使用者,所以在 alert 後面加上 location.reload(); 逼他重新整理 
$(function ()
{
$.ajax({
type: "GET",
url: '/Home/needLogin',
success: function (data)
{
if (data.indexOf("<html") > -1)
{
alert('您尚未登入!');
location.reload();
}
else
{
$('#j_ajax').html(data);
}
}
});
});
對於頁面重整這裡需要非常小心,如果你的網站架構和是未登入會導向到首頁,而那麼剛剛好首頁就有這種需求,就會發生傳說中的「無窮迴圈」頁面一直在重整,因此使用上需要特別小心,千萬不要啥都不知道貼上去就用了。
利用以上方法的確是可以簡單的解決掉這種登入不登入的問題,但 demo 並不知道這種作法正不正確,有沒有更正規的玩法,因此如果有人知道更好的作法,歡迎不吝賜教。
網友回應
- Will

- 發表於: 2010-08-12
- 建議不要用 Authorize 的方式驗證使用者,改在 Action 中自己寫 if 判斷是否登入即可,否則你也可以繼承並自訂 AuthorizeAttribute 屬性類別,可以覆寫 OnAuthorization 方法來實做自訂給 AJAX page 專用當沒有權限時的畫面或回應內容!
- Frank

- 發表於: 2010-07-30
- 對阿!不過這樣兩次 AJAX 似乎不划算呢,ActionFilter 來處理好像比較好,又學了一招,謝過 demo 與 AnYun ^_^
-
互相學習而已^^
回覆於: 2010-07-30
- lastsecret

- 發表於: 2010-07-30
- 在ajax呼叫網址的時候加一個參數 $.ajax({ type: "GET", url: '/Home/needLogin?checkLogOn=1', success: function (data) { $('#j_ajax').html(data); } }); 然後在Login的action上判斷參數是否為空 public ActionResult LogOn(string ppp) { if(!String.IsNullOrEmpty(ppp)){ return Content(寫跳出彈出視窗並且導向LogOn的html); } return View(); } 這樣以後用ajax只要多加個參數就搞定了。
-
這也是一招,感謝分享
回覆於: 2010-07-31
- Will

- 發表於: 2010-07-30
- 可以修改 jQuery 讓 XHR 支援 HTTP 301 的判斷!
-
我在實際測試的時候,會發現因為登出而被導向到登入頁的時候,傳回來的還是 200 (雖然httpwatch 看到的是 301)
回覆於: 2010-07-30
- Frank

- 發表於: 2010-07-30
- 我是 ajax 執行前先檢查 session 是否 timeout (同樣用 ajax request 一個檢查用的 ActionResult), timeout 的話 window.location.replace('登入頁'); 這樣多花一次 request, 好像更糟XD
-
這樣子ajax 的Code是要寫兩次嗎?一次驗證,一次才去做該做的事情?
回覆於: 2010-07-30

