HttpModule.Init - 在 IIS7 集成模式下安全添加 HttpApplication.BeginRequest 处理程序
我的问题类似于但不完全相同:
为什么我的主机 (softsyshosting.com) 不能支持 BeginRequest 和 EndRequest 事件处理程序吗? (我还阅读了其中引用的 mvolo 博客)
目标是在 IHttpModule.Init 事件中成功挂钩 HttpApplication.BeginRequest (或模块内部的任何地方),使用通过 system.webServer 配置集成的普通 HttpModule,即不会:
- 侵入 Global.asax 或
覆盖 HttpApplication(该模块旨在是独立的且可重用的) ,所以例如我有一个像这样的配置):
; <验证validateIntegratedModeConfiguration =“假”/> <模块> <删除名称=“TheHttpModule”/> <添加名称=“TheHttpModule”类型=“Company.HttpModules.TheHttpModule”preCondition=“托管处理程序”/> />
到目前为止,我尝试将侦听器附加到 HttpApplication 的任何策略.BeginRequest 会导致以下两种情况之一,症状 1 是 BeginRequest 永远不会触发,或者症状 2 是在所有托管请求上引发以下异常,并且我无法捕获&amp;从用户代码中处理它:
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 方法主体中删除所有代码,以确保问题不是该方法内部的(=例外)
- 嗅探堆栈跟踪,并且仅在堆栈不是由InitializeApplication启动时调用app.BeginRequest+=...(= BeginRequest未触发)
- 仅在第二次通过Init时调用app.BeginRequest+=(= BeginRequest未触发 )解雇)
有人知道一个好方法吗?是否有一些间接策略可以在模块内挂钩 Application_Start (似乎不太可能)?另一个事件:a)可以从模块的构造函数或 Init 方法中挂钩,b)随后是附加 BeginRequest 事件处理程序的安全位置?
非常感谢
My question is similar but not identical to:
Why can't my host (softsyshosting.com) support BeginRequest and EndRequest event handlers? (I've also read the mvolo blog referenced therein)
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, i.e. one that doesn't:
- invade Global.asax or
override the HttpApplication (the module is intended to be self-contained & reusable, so e.g. I have a config like this):
<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:
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. Init does not reference the Context or Request objects at all.
I have tried:
- Removed all references to HttpContext.Current anywhere in the project (still symptom 1)
- Tested removing all code from the body of my OnBeginRequest method, to ensure the problem wasn't internal to the method (= exception)
- Sniffing the stack trace and only calling app.BeginRequest+=... when if the stack isn't started by InitializeApplication (= BeginRequest not firing)
- Only calling app.BeginRequest+= on the second pass through Init (= BeginRequest not firing)
Anyone know of a good approach? Is there some indirect strategy for hooking Application_Start within the module (seems unlikely)? 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?
Thanks much
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的 HttpModule 的 Init 方法将被单个 Web 应用程序调用多次(而 global.asax 中的 Application_Start 每个 AppDomain 只会调用一次)。
Init 确实是挂接 BeginRequest 的地方。
我也遇到过这个错误,它是由多次挂钩 BeginRequest 事件引起的。我不确定这是否是 IIS 7 集成模式中的错误...
当您执行 app.BeginRequest 时,您是使用 IHttpModule 的 Init 方法的 context 参数调用 context.BeginRequest 还是调用 HttpContext.Current.BeginRequest += ...?
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).
Init is indeed the place to hook onto BeginRequest.
I have encountered this error as well and it was caused by hooking onto the BeginRequest event more than once. I'm not sure if it is a bug in IIS 7 integrated mode or not...
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 += ...?
我遇到了上述相同的问题。我发现实际的解决方法是始终删除然后添加处理程序。因此:
我怀疑在多次调用 init 后,事件处理程序被清除。如果您只在第一次小心地尝试添加事件处理程序,则稍后调用 init 时不会添加事件,因此根本不会调用处理程序。如果您不尝试任何巧妙的方法来限制添加事件的次数,那么您会看到获得多个附件。
首先尝试删除然后添加(在锁内以阻止任何粗糙的竞争条件)似乎可以解决问题。
但这很可怕,我们不应该这样做!
希望有帮助
I had the same problems described above. I found that a practical work around was to always remove then add the handler. thus:
I suspect that the event handlers are getting cleared down after one or more of the multiple calls to the 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. 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