2010-07-29 73 views
8

我們有一個MVC.NET應用程序,它在重新啓動時遇到致命錯誤。在我們的Session_Start事件處理程序中,我們將會話ID添加到字典中。在Session_End處理程序中,我們將其刪除。考慮請求的順序如下:ASP.NET MVC應用程序爲單個會話多次觸發Session_Start

GET home.mvc
<應用程序重新啓動>
GET的main.css
GET banner.jpg
GET somedata.mvc
...

由於應用程序的架構方式,如果在瀏覽器窗口中打開應用程序時執行重建,則這種順序發生的頻率相當高。除非我在生產環境中看到它,否則這不會非常令人擔憂。例如,編輯web.config時會發生(儘管很少)。

重新啓動後的請求全部歸因於主頁中的鏈接或來自JavaScript的AJAX調用。

我觀察到.NET並行處理前5個請求。每個這樣的請求都會導致它觸發Session_Start事件。短時間後,它會觸發Session_End事件3次。要清楚,每個Session_Start對應於完全相同的會話。它們都具有相同的會話ID,IsNewSession屬性對於所有會話狀態對象都是true。另外,Session_End事件而不是對應的會話正在被終止。會話持續存在,以及存儲在會話狀態中的任何數據。

我需要阻止它多次觸發Session_Start,或者想出如何判斷Session_End何時並不意味着會話已經結束。

+0

你需要處理什麼?你是說你的字典和asp.net的內部字典有差異嗎?你在什麼時候發現這種差異? – 2010-07-30 17:41:56

+0

字典是存儲在應用程序變量還是會話變量中? – 2010-07-30 19:38:02

+0

字典是一個應用程序變量。 – 2010-07-30 20:24:46

回答

3

回答這個問題竟然是相當直盼着,雖然這種行爲當然令人困惑。

通常情況下,MVC會將所有請求同步到應用程序的會話狀態鎖定(因爲MVC的http模塊被標記爲需要會話狀態)。在我的場景中,應用程序在服務主頁面後重新啓動。因此,當主頁面相關請求進入時,該會話標識還沒有會話狀態,並且這些請求並行執行。

我看到5個並行請求,因爲我在XP上開發,桌面版本的IIS僅限於5個併發請求。由於這些請求中的任何一個都不存在會話狀態對象,因此每個請求都會創建一個新的會話狀態對象並觸發Session_Start。四個請求轉到MVC操作方法。由於這些需要會話狀態,一旦請求完成,.NET會嘗試將創建的會話狀態對象與後備存儲同步。

只有第一次同步可以成功。 .NET簡單地丟棄三個額外的會話狀態對象併爲每個對象觸發Session_End。 。NET不會嘗試將第五個會話狀態對象與後備存儲同步,因爲它是爲標記爲需要只讀會話狀態的異步http模塊創建的。

因此,修補程序有兩個部分:

(1)我在session_start處理程序,我現在檢查會話狀態對象是隻讀的。如果是這樣,那麼我立即返回而不做任何事情。 .NET不會觸發相應的Session_End,因此我所做的任何事情都無法正確清理。

(2)我現在在我的字典中保留一個引用計數。每當Session_Start處理程序試圖添加一個會話ID並在每次Session_End嘗試刪除它時遞減它,我都會增加計數。一旦計數達到0,我從我的字典中刪除會話ID。

+0

它有點老..但我不追隨爲什麼5個請求是並行的。這是從一個請求中產生的嗎?爲什麼同時創建5個? – 2011-06-07 14:08:27

+0

多個請求同時創建,因爲瀏覽器發送多個請求而無需等待它們返回。 (接收到網頁後,瀏覽器立即請求所有引用的圖像,樣式表等)。因爲機器是Windows XP盒子,所以出現了數字5。 IIS限制應用程序在臺式機上同時處理5個請求。在服務器盒上,數字會更高。 – 2011-06-09 15:15:28

1

如果客戶端向您發送已過期的值,則可以重新使用會話標識。閱讀關於<的sessionState >元素的regenerateExpiredSessionId屬性here並注意默認值是「真」

您也可能會發現this有趣:

+0

謝謝你的回覆馬特,但我相信我一直在吠叫錯誤的樹。我會用昨天發現的一些額外信息更新我的問題。 – 2010-07-30 13:51:48

0

我在開發中遇到過一箇舊的ASP.NET應用程序時,發生了這種情況 - 事實上,RequireSSL被設置爲True以表示cookie ......這當然意味着會話cookie不會被保留/重新發布客戶端(本地主機,非SSL) - 所以後續請求創建了新的會話。

相關問題