简体   繁体   English

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

[英]HttpModule.Init - safely add HttpApplication.BeginRequest handler in IIS7 integrated mode

My question is similar but not identical to: 我的问题类似但不完全相同:

Why can't my host (softsyshosting.com) support BeginRequest and EndRequest event handlers? 为什么我的主机(softsyshosting.com)不支持BeginRequest和EndRequest事件处理程序? (I've also read the mvolo blog referenced therein) (我也读过其中引用的mvolo博客)

The goal is to successfully hook HttpApplication.BeginRequest in the IHttpModule.Init event (or anywhere internal to the module), using a normal HttpModule integrated via the system.webServer config, ie one that doesn't: 目标是成功地在IHttpModule.Init事件(或模块内部的任何地方)中挂钩HttpApplication.BeginRequest,使用通过system.webServer配置集成的普通HttpModule,即不会:

  1. invade Global.asax or 入侵Global.asax或
  2. override the HttpApplication (the module is intended to be self-contained & reusable, so eg I have a config like this): 覆盖HttpApplication(该模块旨在自包含和可重用,所以例如我有这样的配置):

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

So far, any strategy I've tried to attach a listener to HttpApplication.BeginRequest results in one of two things, symptom 1 is that BeginRequest never fires, or symptom 2 is that the following exception gets thrown on all managed requests, and I cannot catch & handle it from user code: 到目前为止,我试图将一个监听器附加到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

Commenting out app.BeginRequest += new EventHandler(this.OnBeginRequest) in Init stops the exception of course. app.BeginRequest += new EventHandler(this.OnBeginRequest)当然会停止异常。 Init does not reference the Context or Request objects at all. Init根本不引用Context或Request对象。

I have tried: 我试过了:

  • Removed all references to HttpContext.Current anywhere in the project (still symptom 1) 在项目的任何位置删除对HttpContext.Current的所有引用(仍然是症状1)
  • Tested removing all code from the body of my OnBeginRequest method, to ensure the problem wasn't internal to the method (= exception) 测试从我的OnBeginRequest方法的主体中删除所有代码,以确保问题不在方法的内部(=异常)
  • Sniffing the stack trace and only calling app.BeginRequest+=... when if the stack isn't started by InitializeApplication (= BeginRequest not firing) 嗅探堆栈跟踪并仅调用app.BeginRequest + = ...如果堆栈未由InitializeApplication启动(= BeginRequest未激活)
  • Only calling app.BeginRequest+= on the second pass through Init (= BeginRequest not firing) 仅在第二次通过Init时调用app.BeginRequest + =(= BeginRequest未触发)

Anyone know of a good approach? 有人知道一个好方法吗? Is there some indirect strategy for hooking Application_Start within the module (seems unlikely)? 在模块中挂钩Application_Start是否有一些间接策略(似乎不太可能)? Another event which a) one can hook from a module's constructor or Init method, and b) which is subsequently a safe place to attach BeginRequest event handlers? 另一个事件:a)可以从模块的构造函数或Init方法挂钩,以及b)随后是附加BeginRequest事件处理程序的安全位置?

Thanks much 非常感谢

Your HttpModule's Init method will get called multiple times by a single web application (whereas Application_Start in your global.asax will only get called once per AppDomain). 您的HttpModule的Init方法将被单个Web应用程序多次调用(而global.asax中的Application_Start只会在每个AppDomain上调用一次)。

Init is indeed the place to hook onto BeginRequest. Init确实是挂钩到BeginRequest的地方。

I have encountered this error as well and it was caused by hooking onto the BeginRequest event more than once. 我也遇到过这个错误,这是因为多次挂钩到BeginRequest事件。 I'm not sure if it is a bug in IIS 7 integrated mode or not... 我不确定它是否是IIS 7集成模式中的错误...

When you do app.BeginRequest are you calling context.BeginRequest using the context parameter to your IHttpModule's Init method or are you calling HttpContext.Current.BeginRequest += ...? 当您执行app.BeginRequest时,您是使用上下文参数调用context.BeginRequest到您的IHttpModule的Init方法还是调用HttpContext.Current.BeginRequest + = ...?

I had the same problems described above. 我遇到了上述相同的问题。 I found that a practical work around was to always remove then add the handler. 我发现一个实际的工作是始终删除然后添加处理程序。 thus: 从而:

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

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

I suspect that the event handlers are getting cleared down after one or more of the multiple calls to the init. 我怀疑在多次调用init之后,事件处理程序会被清除。 If you carefully only try and add the event handler the first time, the later times init gets called don't get a event added and hence the handler doesn't get called at all. 如果你第一次小心地尝试添加事件处理程序,那么init被调用的时间越晚,就不会添加事件,因此根本不会调用处理程序。 If you don't try anything cunning to limit the number of times the event gets added, then you seen to get multiple attachments. 如果您不尝试任何狡猾的事情来限制事件的添加次数,那么您会看到获得多个附件。 By first trying to remove then add (inside a lock to stop any gnarly race conditions) seems to do the trick. 通过首先尝试删除然后添加(在锁内停止任何粗糙的竞争条件)似乎做的伎俩。

It is horrible though, and we shouldn't have to do this! 虽然很可怕,但我们不应该这样做!

Hope that helps 希望有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM