13

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

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

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

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

    <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
      <remove name="TheHttpModule" />
      <add name="TheHttpModule" type="Company.HttpModules.TheHttpModule" preCondition="managedHandler" /> 
    

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

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

在 Init 中注释掉app.BeginRequest += new EventHandler(this.OnBeginRequest)当然会停止例外。Init 根本不引用 Context 或 Request 对象。

我努力了:

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

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

非常感谢

4

2 回答 2

3

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

Init 确实是连接 BeginRequest 的地方。

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

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

于 2010-09-14T20:34:19.873 回答
1

我遇到了上述相同的问题。我发现一个实际的解决方法是始终删除然后添加处理程序。因此:

    public override void Init()
    {
        base.Init();

        lock (_initialisationLockObject)
        {
            BeginRequest -= Global_BeginRequest;
            BeginRequest += Global_BeginRequest;
        }
    }

我怀疑在对 init 进行多次调用中的一次或多次之后,事件处理程序正在被清除。如果您只在第一次小心地尝试添加事件处理程序,则稍后调用 init 不会添加事件,因此根本不会调用处理程序。如果您不尝试任何巧妙的方法来限制添加事件的次数,那么您会看到获得多个附件。通过首先尝试删除然后添加(在锁内以停止任何粗糙的竞争条件)似乎可以解决问题。

这太可怕了,我们不应该这样做!

希望有帮助

于 2015-02-06T09:29:01.363 回答