Mar*_*inF 31 .net c# init httpmodule
我正在创建一个http模块,在调试时我注意到一些东西,起初(至少)看起来像是奇怪的行为.
当我在httpmodule的init方法中设置断点时,我可以看到http模块初始化方法被多次调用,即使我只是启动了网站进行调试并发出了一个单一请求(有时它只被命中一次) ,其他时间多达10次).
我知道我应该期望HttpApplication的几个实例正在运行,并且每个http模块都将被创建,但是当我请求单个页面时,它应该由单个http应用程序对象处理,因此只触发关联一次的事件,但是它仍然会为每个请求多次触发事件,这是没有意义的 - 除了它必须在httpApplication中多次添加 - 这意味着它是每次调用的相同的httpmodule init方法而不是新的http应用程序每次碰到我的断点时都会被创建(请参阅底部的代码示例等).
这可能会出错?是因为我正在调试并在http模块中设置断点?
它已经注意到,如果我启动网站进行调试并快速跳过httpmodule中的断点,它只会触发一次init方法,而事件处理程序也是如此.如果我让它在断点处挂起几秒钟,则会多次调用init方法(看起来这取决于我在跨越断点之前等待多长时间).也许这可能是一些内置功能,以确保httpmodule已初始化,http应用程序可以提供请求,但它似乎也可能产生灾难性后果.
这似乎是合乎逻辑的,因为它可能正在尝试完成请求,因为我设置了断点,它认为出了问题,并尝试再次调用init方法?它可以处理请求吗?
但这是发生了什么,一切都很好(我只是猜测),还是一个真正的问题?
我特别关注的是,如果有什么东西让它挂在"生产/实时"服务器上几秒钟,那么很多事件处理程序都会通过init添加,因此每次对页面的请求都会突然激活事件处理程序几次.
此行为可能会迅速导致任何网站崩溃.
我查看了用于formauthentication和rolemanagermodule等的httpmodules的"原始".net代码,但我的代码与这些模块使用的代码不同.
我的代码看起来像这样.
public void Init(HttpApplication app)
{
if (CommunityAuthenticationIntegration.IsEnabled)
{
FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];
formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个如何在.NET框架的RoleManagerModule中完成它的示例
public void Init(HttpApplication app)
{
if (Roles.Enabled)
{
app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
app.EndRequest += new EventHandler(this.OnLeave);
}
}
Run Code Online (Sandbox Code Playgroud)
有谁知道发生了什么?
(我只希望有人可以告诉我为什么会这样,并向我保证一切都很好):)
更新:
我试图缩小问题的范围,到目前为止,我发现被调用的Init方法总是在我的http模块的一个新对象上(与我之前想到的一致).
我似乎对于第一个请求(启动站点时)所有正在创建的HttpApplication对象及其模块都试图为第一个请求提供服务,因此所有HttpApplication都会触发正在添加的事件处理程序.我无法弄清楚为什么会这样.
如果我请求另一个页面,所有创建的HttpApplication(以及它们的无模块)将再次尝试提供请求,使其多次命中eventhandler.
但似乎如果我然后跳回到第一页(或另一个),只有一个HttpApplication将开始处理请求,一切都按预期 - 只要我不让它挂在断点.
如果我让它在断点处挂起它开始创建新的HttpApplication对象并开始添加HttpApplications(超过1)来提供/处理请求(已经在HttpApplication服务的过程中,当前在断点处停止) .
我想或希望它可能是一些帮助分发和处理负载和/或错误的智能"幕后"方式.但我不知道.我希望有些人可以向我保证它完全没问题,它应该如何?
Sun*_*oot 42
Init()方法被多次调用是正常的.当一个应用程序启动时,ASP.NET Worker进程将实例化它认为需要的HttpApplication对象,然后它们将它们集中在一起(例如,为新请求重用它们,类似于数据库连接池).
现在,对于每个HttpApplication对象,它还将实例化已注册的每个IHttpModule的一个副本,并多次调用Init方法.因此,如果创建了5个HttpApplication对象,将创建5个IHttpModule副本,并且您的Init方法调用5次.合理?
现在为什么它实例化5个HttpApplications对象呢?好吧,也许您的ASPX页面链接到您的浏览器将尝试下载的其他资源,css,javascript,WebResource.aspx,也许是某个地方的iframe.或者,ASP.NET Worker Process可能会"启动"多个HttpApplication对象,这实际上是在IIS(或内置于Web服务器中的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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经做了类似的事情似乎工作,但我欢迎批评我的工作,以防我错过了什么.
检查HttpContext.Current.Request以查看模块的init被触发的请求.可能是浏览器发送多个请求.
如果您已连接到IIS,请检查IIS日志以了解您在断点处停留时是否收到任何请求.
| 归档时间: |
|
| 查看次数: |
20288 次 |
| 最近记录: |