[ASP.NET] MVC 3上,Session消失的問題與解決辦法

筆者因工作因素,不得不碰Microsoft MVC 3。雖然開發方便,不過他隱含的一些奇怪的Bug也不少。
身為一個網站開發人員,時常會用到Cookie與Session。奇怪的點就在於MS Visual Studio 2010在開發MVC 3時,有時候會為了某些奇怪因素,重新啟動你開發的Application。
目前普遍知道的重新啟動事件,可能會於以下情形發生:

  1. 從應用程式的 Bin 資料夾中加入、修改或刪除組件。
  2. 從 App_GlobalResources 或 App_LocalResources 資料夾中加入、修改或刪除當地語系化資源。
  3. 加入、修改或刪除應用程式的 Global.asax 檔。
  4. 在 App_Code 目錄中加入、修改或刪除原始程式碼檔。
  5. 加入、修改或刪除設定檔組態。
  6. 在 App_WebReferences 目錄中加入、修改或刪除 Web 服務參考。
  7. 加入、修改或刪除應用程式的 Web.config 檔。
  8. 防毒軟體剛好掃到Webconfig檔
然而,筆者最近發現兩個更奇怪的重新啟動狀況!
  1. Application restarts on directory delete in ASP.net
  2. 檔案上傳後,在該Action內直接return RedirectToAction() ;
開發MVC 3 or ASP.NET網站人員應該都知道,在SessionState為InProc的設定下,任何重新啟動( or Application_start函數的呼叫),將導致Session消失
很不巧地,筆者剛好遇到上述第2種狀況,導致Session消失,Debug 10個小時才抓到此嚴重錯誤。
其實上面第 2種狀況,應該算是「 Bin 資料夾中加入、修改或刪除組件」,從下面程式碼便可知一二:
public ActionResult Access()
{
// 取出剛剛上傳的檔名,這邊會發現取不到值
string fileName = TempData["upfile"].ToString();
/*
* 處理的程式區段
*/
return View();
}

[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
//檢查是否有檔案上傳,有的話存檔
if (file !=null && file.ContentLength > 0)
{
//放在執行檔目錄中Upload目錄底下
string savedName = "./Upload/" + file.FileName;
file.SaveAs(savedName);
TempData["upfile"]=file.FileName;
}

return RedirectToAction("Access");
}
從上述可知,由於我在檔案上傳時,”增加”了bin資料夾下的組件,導致Application_start()函數再次啟動,使得我的Session就這麼消失了。

為了避免這個錯誤一再重演,建議將Session State設定為StateServer或是SQL Server模式。
將Session State設定為State Server的方法,可看這篇「如何讓 ASP.NET 使用 Session 資料時不要再自動消失」,主要兩個步驟:
1. 啟動 aspnet_state.exe (ASP.NET State Service)
2. 在Web.config中,加入以下這段設定:

<configuration>
  <system.web>
    <sessionState mode=”StateServer”
      stateConnectionString=”tcpip=localhost:42424″
      cookieless=”false”
      timeout=”20″/>
  </system.web>
</configuration>

需要注意設定的Web.config檔案的出處。(不知道為什麼,筆者的View資料夾下剛好也有Web.config,若手誤設定到這個,執行會錯誤喔!)

為了追求開發出來的程式不因Application重新啟動而造成不穩定狀況 (例如:筆者遇到的檔案上傳導致無法儲存Session的問題,也是透過部署的方式,立刻解決!)。
我們通常會需要用到部署,至於設定部署功能,請跟著筆者這樣子做:
  1. 請先安裝好IIS  6/7
  2. 若是使用ASP.NET 4.0,ASP.NET 4.0的安裝程式,不會連同IIS一起設定,因此,請按照此方法設定。
  3. 從IIS中,設定好網站目錄 or 虛擬目錄
  4. 設定單鍵發行功能,方法請看如何使用 Visual Studio 2010 的「單鍵發行」功能 (MsDeploy)
另一個可能發生的問題,則是在負載平衡的 Web 伺服陣列環境執行 ASP.NET Web 應用程式時,如果使用 SqlServer 或 StateServer 工作階段模式,工作階段狀態可能會遺失
解決辦法在微軟的「PRB:如果您使用 SqlServer 或 StateServer 工作階段模式,Web 伺服陣列中的工作階段狀態會遺失」,剛好遇到這類問題的使用者,可以看一看。


Reference

  1. [.NET] ASP.NET 狀態管理(State Management):Session
  2. [ASP.NET] Session 遺失 / Session Timeout / Session 設定
  3. 如何讓 ASP.NET 使用 Session 資料時不要再自動消失
  4. IIS虛擬目錄設定
  5. ASP.NET IIS設定工具
  6. ASP.NET 應用程式生命週期概觀
  7. ASP.NET MVC Request Flow (推薦閱讀!)
  8. ASP.NET MVC 3概觀正體中文版 (推薦閱讀!)

About the Author

Leave a Reply

Your email address will not be published. Required fields are marked *

You may also like these