如何限制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中:

         

我在HttpModuleRewriter类的’Init’方法中加入了断点。 应用程序启动时调用第一次方法…每个页面请求只调用一次模块。

如果我对页面请求很快(第二个请求将在第一个请求被处理之前发送),那么方法’Init’会被少量调用,每个跟随页面的请求会导致2-3次调用我的模块…

为什么? 我怎么能避免这种情况?

谢谢。

PS我已经将公共构造函数添加到HttpModuleRewriter中以计算引用量,并且在我的请求期间我创建了5个模块…并且对于每个页面2模块的请求实际上被调用…但仅针对第一个导航页面,以下所有页面(我已经检查了3个其他页面)模块只被调用一次(只调用了1个实例)…

为什么第一页被处理两次? 建议的答案(使用’初始化’标志)也无济于事。

如果在第二个请求出现之前Init()还没有完成,那么你的HttpModule还没有准备好。 如果您的Init()方法中的代码只能运行一次,那么您可以设置一个标志(bool初始化)并使用锁来防止代码由多个线程运行,例如:

 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; } } } 

更新:正如本文所解释的,ASP.NET可能会创建多个HttpModule实例,因此可以多次调用Init()。 这是设计的。 因此,您必须设计模块,以便应该只运行一次的代码只运行一次 – 通过应用锁定,如上所述。

我要说明显的答案是你的处理程序正在处理多个请求,可能是样式表或图像。

将以下内容添加到ProcessRequest事件处理程序中,并向context.Request.PhysicalPath添加监视以确认此操作。

 HttpApplication application = (HttpApplication)sender; HttpContext context = application.Context; string filename = Path.GetFileName(context.Request.PhysicalPath); 

如果您不希望处理程序为图像请求等运行,那么您需要做的就是检查以“.aspx”结尾的路径或类似的东西。

当您执行两次Init()时,BeginRequest事件将调用两次处理,因为它有两个事件处理程序。 + =运算符在列表中添加新事件处理程序,它不替换旧处理程序。

Øyvind有一个正确的解决方案。