2011-04-01 82 views
1

這是我實現的HttpModule的:如何限制HttpModule每個請求只有一個呼叫?

文件與模塊:

public class HttpModuleRewriter : IHttpModule 
{ 
    #region IHttpModule 

    public void Init(HttpApplication app) 
    { 
     app.BeginRequest += ProcessRequest; 
    } 

    public void Dispose() 
    { 
    } 

    #endregion 

    #region Protected Methods 

    protected void ProcessRequest(object sender, EventArgs e) 
    { 
     ... 
    } 
} 

的web.config:

<?xml version="1.0"?> 
<configuration> 
    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"> 
     <add name="HttpModuleRewriter" preCondition="managedHandler" type="HttpModuleRewriter" /> 
    </modules> 
    </system.webServer> 
</configuration> 

我把破發點中的HttpModuleRewriter類的 '初始化' 的方法。第一次方法在應用程序啓動時被調用...並且每個頁面請求調用模塊只有一次。

如果我趕緊做請求的頁面(第2請求將早於1日請求被處理後發送),那麼方法「初始化」另外幾個叫每個如下要求的網頁導致2-3呼叫我的模塊...

爲什麼?我怎麼能避免這種情況?

謝謝。

P.S.我已經將公共構造函數添加到HttpModuleRewriter中以計算引用的數量,並且在我的請求期間,我創建了5個模塊...並且對於頁面2的每個請求模塊實際上都被稱爲...但僅用於第一個導航頁面以下頁面(我檢查了3個其他頁面)模塊只被調用一次(僅調用1個實例)...

爲什麼第一頁被處理兩次?建議的答案(使用「初始化」標誌)也無濟於事。

回答

5

如果初始化()的第二請求出現之前尚未完成那麼你的HTTP模塊還沒有準備好。如果你有一些代碼在您的初始化應該只運行一次,那麼你可以設置一個標誌(布爾初始化)()方法,並使用鎖來防止由多個線程運行的代碼,如:

private static bool initialised; 
private static object lockObject = new object(); 

public void Init(HttpApplication app) 
{ 
    lock(lockObject) 
    { 
     if(!initialised) 
     { 
      app.BeginRequest += ProcessRequest; 
      //... other code here 
      initialised = true; 
     } 
    } 
} 

更新: 作爲this article解釋說,ASP.NET可以創建你的HttpModule的多個實例,因此,init()可以多次調用。這是設計。因此,您必須對模塊進行調整,以便僅應運行一次的代碼只能運行一次 - 通過應用鎖定(如上所述)。

+0

所以,你認爲模塊初始化兩次或更多次都可以嗎? ......可能你是對的。謝謝。 – Budda 2011-04-01 21:51:10

+0

但我想,你應該使用靜態變量'已初始化'的字段。 – Budda 2011-04-01 21:51:39

+0

似乎asp.net應用程序創建一個新的模塊,如果沒有其他可用。如果您沒有將當前創建的模塊的ProcessRequest分配給app.BeginRequest,那麼以下嘗試調用模塊將不會像預期的那樣調用'ProcessRequest'方法...因此模塊將不會實際連接。建議的解決方案似乎不可行。 – Budda 2011-04-01 22:29:30

3

我想說的顯而易見的答案是,你的操作是處理多個請求,可能用於樣式表或圖像。

將以下內容添加到您的ProcessRequest事件處理程序中,並將一個手錶添加到context.Request.PhysicalPath以確認這一點。

HttpApplication application = (HttpApplication)sender; 
HttpContext context = application.Context; 

string filename = Path.GetFileName(context.Request.PhysicalPath); 

如果你不想讓你的處理程序爲圖像等的要求運行,所有你需要做的是檢查結束「的.aspx」或類似的路徑。

1

當您執行的init()兩次,BeginRequest事件將調用兩次你的處理,因爲它有兩個事件處理程序在裏面。 + =操作符將新的事件處理程序添加到列表中,它不會替換舊的處理程序。

Øyvind有一個正確的解決方案。