HttpModule.Init – 在IIS7集成模式下安全地添加HttpApplication.BeginRequest处理程序

我的问题类似但不完全相同:

为什么我的主机(softsyshosting.com)不支持BeginRequest和EndRequest事件处理程序? (我也读过其中引用的mvolo博客)

目标是成功地在IHttpModule.Init事件(或模块内部的任何地方)中挂钩HttpApplication.BeginRequest,使用通过system.webServer配置集成的普通HttpModule,即不会:

  1. 入侵Global.asax或
  2. 覆盖HttpApplication(该模块旨在自包含和可重用,所以例如我有这样的配置):

         

到目前为止,我试图将一个侦听器附加到HttpApplication.BeginRequest的任何策略都会产生以下两种情况之一:症状1是BeginRequest永远不会触发,或者症状2是所有托管请求都抛出以下exception,我不能从用户代码中捕获并处理它:

 Stack Trace: [NullReferenceException: Object reference not set to an instance of an object.] System.Web.PipelineModuleStepContainer.GetEventCount(RequestNotification notification, Boolean isPostEvent) +30 System.Web.PipelineStepManager.ResumeSteps(Exception error) +1112 System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +113 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +616 

app.BeginRequest += new EventHandler(this.OnBeginRequest)当然会停止exception。 Init根本不引用Context或Request对象。

我试过了:

  • 在项目的任何位置删除对HttpContext.Current的所有引用(仍然是症状1)
  • 测试从我的OnBeginRequest方法的主体中删除所有代码,以确保问题不在方法的内部(=exception)
  • 嗅探堆栈跟踪并仅调用app.BeginRequest + = …如果堆栈未由InitializeApplication启动(= BeginRequest未启动)
  • 只在第二次通过Init时调用app.BeginRequest + =(= BeginRequest未激活)

有人知道一个好方法吗? 在模块中挂钩Application_Start是否有一些间接策略(似乎不太可能)? 另一个事件:a)可以从模块的构造函数或Init方法挂钩,以及b)随后是附加BeginRequest事件处理程序的安全位置?

非常感谢

您的HttpModule的Init方法将被单个Web应用程序多次调用(而global.asax中的Application_Start只会在每个AppDomain上调用一次)。

Init确实是挂钩到BeginRequest的地方。

我也遇到过这个错误,它是由多次挂钩到BeginRequest事件引起的。 我不确定它是否是IIS 7集成模式中的错误…

当您执行app.BeginRequest时,您是使用上下文参数调用context.BeginRequest到您的IHttpModule的Init方法还是调用HttpContext.Current.BeginRequest + = …?

我遇到了上述相同的问题。 我发现一个实际的工作是始终删除然后添加处理程序。 从而:

  public override void Init() { base.Init(); lock (_initialisationLockObject) { BeginRequest -= Global_BeginRequest; BeginRequest += Global_BeginRequest; } } 

我怀疑在多次调用init之后,事件处理程序会被清除。 如果您第一次小心地尝试添加事件处理程序,则稍后调用init时不会添加事件,因此根本不会调用处理程序。 如果您不尝试任何狡猾的事情来限制事件的添加次数,那么您会看到获得多个附件。 通过首先尝试删除然后添加(在一个锁内停止任何粗糙的竞争条件)似乎做的伎俩。

虽然很可怕,但我们不应该这样做!

希望有所帮助