2017-04-24 149 views
1

在我的應用程序中,我將對象存儲到會話中,該會話被傳遞給Web服務以返回數據以顯示在表中。如果會話存在,則它不會要求用戶輸入新的數據。但是,如果用戶選擇一個名爲「新列表」的鏈接,則會話數據將被清除,並且用戶提示輸入新數據。c#mvc:RedirectToAction()和瀏覽器導航按鈕

在我的代碼,我已經定義了以下這樣一個錨:

<a href="@Url.Action("NewList", "Alert")"> New List</a> 

將觸發此控制器操作:

public ActionResult NewList() 
{ 
    Session["new_list"] = "y"; 
    return RedirectToAction("List"); 
} 

然後繼續執行這個動作:

public ActionResult List() 
    { 
     if ((string)Session["new_list"] == "y") 
     { 
      //clear session variables, load fresh data from API 
     }else{ 
      //display blank table. Ask user to input data to retrieve a list 
     } 
     .... 
    } 

現在,我遇到的問題是當用戶導航離開列表頁面,然後導航回wi th瀏覽器的後退按鈕,它仍然呼籲newlist。在瀏覽器的歷史中,不是存儲List,而是存儲newlist,這導致會話變量清除。我能做些什麼來阻止這種情況的發生,或者是否有其他機制可以在c#mvc中使用,這可以幫助我實現預期的效果。

+0

把它放入cookie中。 – CodingYoshi

回答

1

你的主要這裏的問題是,NewList操作使用GET時,它應該是一個POST

A GET請求永遠不會改變資源的狀態,而只是返回資源的當前狀態;而POST請求允許改變資源。因爲你允許用GET請求調用NewList動作,所以用戶的瀏覽器假定(完全正確地),如果它僅僅在將來重複請求,就會發生沒有不好的/不想要的事情,例如,當用戶使用後退按鈕時。

如果發出POST請求,用戶瀏覽器將不會重新發出請求,而用戶不確認它們實際上是否打算重新發出請求。

你的問題的解決方案則是修改此爲標準PRG模式:POST /重定向/ GET;即發送POST請求以執行狀態更改,將用戶瀏覽器重定向到另一個頁面,並獲取結果頁面。在這種方案中,按下後退按鈕將有效地「跳過」狀態改變操作並轉到用戶所在的上一頁。

要在MVC實現這一點:

[HttpPost] 
public ActionResult NewList() 
{ 
    //clear session variables, load fresh data from API 
    return RedirectToAction("List"); 
} 

public ActionResult List() 
{ 
    // whatever needs to happen to display the state 
} 

這意味着你不能直接提供「新目錄」行動,在頁面的超鏈接,因爲這些總會發出GET請求。您需要使用如下所示的最小表單:<form method="post" action="@Url.Action("NewList", "Alert")"><button type="submit">New List</button></form>。您可以根據需要設置按鈕的樣式,使其看起來像普通的超鏈接。

+0

這是一個很好的解決方案。感謝您花時間回答。儘管我認爲我可能找到了一個較短的解決方案,即在動作定義上方使用'[HttpGet,OutputCache(NoStore = true,Duration = 1)]'。這將迫使瀏覽器從頭開始加載頁面,而不是從緩存中加載頁面。這是目前正在發生的情況 – Notaras

+0

我不認爲你的問題與緩存有什麼關係,尤其是因爲你注意到用戶按下後退按鈕將無意中清除他們的列表(表示瀏覽器發出請求到服務器,並沒有從它的緩存服務它!) 也有安全方面的考慮因素,考慮到在你目前的方案下,我可以在另一個網站上放置一個

0

它存儲NewList的原因是因爲您正在重定向到「Alert/NewList」,並且它的URL中的字符串用於打到「NewList」操作,所以無論何時嘗試返回按鈕,瀏覽器都會獲取此「Alert/NewList「的URL,因此它打擊行動」新列表「。 但現在,我不明白爲什麼會話變得清晰。因爲你在「NewList」本身初始化會話。不過,我建議你使用本地存儲來爲會話分配值。