HttpModule Init方法被称为好几次-为什么?
-
16-09-2019 - |
题
我是创造一个http模块和调试时,我注意到一些东西,在第(至少)看起来像怪怪的行为。
当我设置一个断点在init方法的httpmodule我可以看到,http模块init方法被称为若干次即使我只启动了该网站的调试和作出一个单一的请求(有时是命中只有1时,其他时间多10次)。
我知道,我应该想到几个实例HttpApplication运行,并为每个http模块将创建的,但是,当我请一个单一的页面应当处理通过一个单http应用程序的对象,因此只有火的事件相关的一次, 但是它仍然大火的事件几次为每个请求,这使得没有意义-比它必须已经加入若干时间内,httpApplication-这意味着它是一样的httpmodule init方法,该方法被称为每一次而不是一个新http应用程序,正在创造的每一次碰我的休息点(见我的代码如在底部等等)。
什么可能会错误在这里?是因为我调试,并设置一个断点在http模块?
它已经注意到,似乎如果我启动该网站的调试和迅速步骤在断点在httpmodule它只会打init方法一旦和同样的处理.如果我不是让它挂在断点几秒的初始方法被称为若干次(在看来似乎取决于如何很长一段时间我之前等待加强了断点).也许这可能是一些建立在功能,以确保httpmodule初始化和http应用程序可以为请求提供服务,但它似乎也喜欢的东西,可能具有灾难性的后果。
这可能似乎是合乎逻辑的,因为它可能试图完成的要求和自我设定的折点,它认为什么出了问题,并试图呼叫init方法了吗?soo它可以处理的请求?
但是这个正在发生的事情和一切现(我只是猜的),或者是一个现实问题吗?
我特别感到关切的是,如果有什么让它挂在"生产/生活"的服务器几秒钟的很多事件的处理程序加入通过初始化,因此每一请求的网页,突然火灾的处理若干倍。
这种行为可能迅速带来的任何网站下来。
我已经看过的"原"。净码用于httpmodules为formsauthentication和rolemanagermodule等,但我的代码不是任何不同,这些模块的用途。
我的代码看起来是这样的。
public void Init(HttpApplication app)
{
if (CommunityAuthenticationIntegration.IsEnabled)
{
FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];
formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
}
}
这里是一个例子,它是如何做的RoleManagerModule。净框架
public void Init(HttpApplication app)
{
if (Roles.Enabled)
{
app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
app.EndRequest += new EventHandler(this.OnLeave);
}
}
这样做的人知道是怎么回事?
(我只是希望有人能告诉我为什么发生这种情况,并向我保证一切都是完美的):)
更新:
我试图缩小该问题,到目前为止,我们发现,Init方法被称为是总是在一个新的目的我http模块(contary到我的想法之前)。
我似乎认为第一个请求(时启动的网站)的所有HttpApplication对象的创建及其模块都试图为第一个请求以及因此所有击中处理,是正在增加。我不能真正弄清楚为什么会发生这种情况。
如果我请求另一页的所有HttpApplication是创建(和其moduless)将再次尝试为该请求引起它打的处多次。
但它也看来,如果我然后跳回到第一页(或者另外一个)只有一个HttpApplication将开始照顾的请求,一切都是预料之中的-只要我不要让它挂在一个断点。
如果我让它挂在一个断点开始新建HttpApplication的对象,并开始加入HttpApplications(超过1)服务/处理的请求(这是已经在进程正在通过HttpApplication这是目前停在断点).
我想或希望,这可能是一些智能的"幕后"的方式帮助分发和处理负荷和/或错误。但我没有任何线索。我希望一些在那里可以向我保证,它是完美以及它是如何应该是什么?
解决方案
检查HttpContext.电流。请求中看到的,为什么请求模块的init被解雇。可以浏览器发送多的请求。
如果你是连到IIS,做检查IIS日志知道是否有任何收到请求的时候,你是住在破点。
其他提示
,这是正常的init()方法被调用多次。当一个应用程序启动时,它认为它需要ASP.NET工作进程将实例尽可能多的HttpApplication对象,那么它会集中他们(如resuse他们为新的请求,这与数据库连接池)。
现在对每个HttpApplication对象,它也将实例化每个被登记的IHttpModule的一个拷贝,并调用Init方法,许多次。因此,如果创建5个的HttpApplication对象,你的IHttpModule的5个人副本将被创建,并要求5倍的Init方法。有意义吗?
现在为什么它实例5 HttpApplications对象说什么?嗯,也许你的ASPX页面有其他资源的链接,你的浏览器将尝试下载,CSS,Javascript代码,WebResource.aspx,也许一个iframe的地方。或者,也许ASP.NET工作进程“处于情绪”用于开始超过1个HttpApplication对象,这是真的IIS(或内置于网络服务器的VS)下运行的ASP.NET过程的内部细节/优化
如果你想有保证只运行一次(并且不希望使用在Global.asax的Application_StartUp事件)的代码,你可以尝试在你的IHttpModule以下内容:
private static bool HasAppStarted = false;
private readonly static object _syncObject = new object();
public void Init(HttpApplication context)
{
if (!HasAppStarted)
{
lock (_syncObject)
{
if (!HasAppStarted)
{
// Run application StartUp code here
HasAppStarted = true;
}
}
}
}
我做过类似的东西,它似乎工作,虽然我会欢迎我的工作的批评的情况下,我已经错过了一些东西。
下面是一些解释,以你应该用什么,什么时候,以及它们如何工作。 何时在Global.asax中使用的Application_Start VS初始化一>
编辑:更多读数
Examle锁定IHttpModule的所有请求,然后,它frezes整个应用程序。 如果您的通话IHttpModule的请求多次需要调用HttpApplication的方法CompleteRequest,为了去除的HttpApplication实例这样处置的IHttpModule的一个HttpApplication实例在EndRequest事件:
public class TestModule :IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
app.CompleteRequest();
app.Dispose();
}
void context_BeginRequest(object sender, EventArgs e)
{
//your code here
}
#endregion
}
如果您需要IHttpModule的请求每次没有再请求回发使用上面这段代码。