IHttpModule.BeginRequest 触发 2X,Application_BeginRequest 触发 1X
我正在运行 VS 2008 和 .NET 3.5 SP1。
我想在 ASP.NET 应用程序的 HttpModule
中实现点击跟踪。我想,很简单。但是,我的 HttpModule
的 BeginRequest
事件对于每个页面点击都会触发两次。该网站现在非常简单......没有安全性,只有一些数据库工作。每点击一页应记录一行。为什么这个事件会触发两次?
此外,IHttpModule.BeginRequest
实际上在第一次运行时(从关闭的 Web 浏览器)触发首页点击的次数不同...当我点击数据库时触发了 3 次为页面提供动态数据,对于未命中数据库的页面仅提供 1 次。无论我是否正在接触数据库,在第一个页面之后点击的每个页面都会触发两次。
有趣的是,Application_BeginRequest
(在 Global.asax
中)始终只触发一次。
这是代码:
using System;
using System.Data;
using System.Data.Common;
using System.Net;
using System.Web;
using BluHeron.BusinessLayer;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;
namespace BluHeron.HttpModules
{
public class SiteUsageModule : IHttpModule
{
public void Init(HttpApplication httpApp)
{
httpApp.BeginRequest += OnBeginRequest;
}
static void OnBeginRequest(object sender, EventArgs a)
{
UsageLogger.LogSiteUsage(((HttpApplication)sender).Context.Request);
}
public void Dispose()
{ }
}
public static class UsageLogger
{
public static void LogSiteUsage(HttpRequest r)
{
string ipAddress = GetHostAddress(Dns.GetHostAddresses(Dns.GetHostName()));
string browserVersion = r.Browser.Type;
string[] urlChunks = r.RawUrl.Split('/');
string page = urlChunks[urlChunks.GetLength(0)-1];
SqlDatabase db = new SqlDatabase(Common.GetConnectionString());
DbCommand cmd = db.GetStoredProcCommand("LogUsage");
db.AddInParameter(cmd, "IPAddress", SqlDbType.NVarChar, ipAddress);
db.AddInParameter(cmd, "BrowserVersion", SqlDbType.NVarChar, browserVersion);
db.AddInParameter(cmd, "PageName", SqlDbType.NVarChar, page);
db.AddInParameter(cmd, "Notes", SqlDbType.NVarChar, "");
db.ExecuteNonQuery(cmd);
}
private static string GetHostAddress(IPAddress[] addresses)
{
foreach (IPAddress ip in addresses)
{
if (ip.ToString().Length <= 15)
{
return ip.ToString();
}
}
return "";
}
}
}
I'm running VS 2008 and .NET 3.5 SP1.
I want to implement hit tracking in an HttpModule
in my ASP.NET app. Pretty simple, I thought. However, the BeginRequest
event of my HttpModule
is firing twice for each page hit. The site is very simple right now...no security, just a bit of database work. Should log one row per page hit. Why is this event firing twice?
Moreover, IHttpModule.BeginRequest
actually fires a different number of times for the first page hit when running for the first time (from a closed web browser)...3 times when I'm hitting the DB to provide dynamic data for the page, and only 1 time for pages where the DB isn't hit. It fires 2 times for every page hit after the first one, regardless of whether or not I'm touching the DB.
It's interesting to note that Application_BeginRequest
(in Global.asax
) is always firing only once.
Here's the code:
using System;
using System.Data;
using System.Data.Common;
using System.Net;
using System.Web;
using BluHeron.BusinessLayer;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;
namespace BluHeron.HttpModules
{
public class SiteUsageModule : IHttpModule
{
public void Init(HttpApplication httpApp)
{
httpApp.BeginRequest += OnBeginRequest;
}
static void OnBeginRequest(object sender, EventArgs a)
{
UsageLogger.LogSiteUsage(((HttpApplication)sender).Context.Request);
}
public void Dispose()
{ }
}
public static class UsageLogger
{
public static void LogSiteUsage(HttpRequest r)
{
string ipAddress = GetHostAddress(Dns.GetHostAddresses(Dns.GetHostName()));
string browserVersion = r.Browser.Type;
string[] urlChunks = r.RawUrl.Split('/');
string page = urlChunks[urlChunks.GetLength(0)-1];
SqlDatabase db = new SqlDatabase(Common.GetConnectionString());
DbCommand cmd = db.GetStoredProcCommand("LogUsage");
db.AddInParameter(cmd, "IPAddress", SqlDbType.NVarChar, ipAddress);
db.AddInParameter(cmd, "BrowserVersion", SqlDbType.NVarChar, browserVersion);
db.AddInParameter(cmd, "PageName", SqlDbType.NVarChar, page);
db.AddInParameter(cmd, "Notes", SqlDbType.NVarChar, "");
db.ExecuteNonQuery(cmd);
}
private static string GetHostAddress(IPAddress[] addresses)
{
foreach (IPAddress ip in addresses)
{
if (ip.ToString().Length <= 15)
{
return ip.ToString();
}
}
return "";
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这对于答案来说可能为时已晚,但对其他人可能有用。我面临着同样的问题。每个请求都会触发 BeginRequest 事件两次。我调试了代码并意识到第一个触发器是实际资源请求,但第二个触发器是“favicon.ico”请求的结果。在 BeginRequest 事件开始时,对 favicon.ico 请求的简单检查消除了该方法的第二次执行。
This might be too late for the answer but can be useful for someone else. I faced with the same problem. BeginRequest event triggered for twice for each request. I debugged the code and realized that the first trigger for actual resource request but the second is result of "favicon.ico" request. At the beginning of BeginRequest event, a simple check for favicon.ico request eliminates second execution of the method.
很晚了,但遇到了同样的问题。在我们的例子中,这是由于匿名请求首先根据 RFC 返回 401。第二个请求进行身份验证。
quite late on this, but ran into the same issue. In our case it was due to the anonymous request first that returns the 401 per the RFC. The second request authenticates.
我们通过使用解决了这个问题
,这应该可以防止您看到的两次火灾。
We solved this by using
This should prevent the the twice fire you are seeing.
IIS 的“默认文档”部分似乎触发了第二个
BeginRequest
事件。如果您确定两个事件处理程序中的
Request.Path
与HttpApplication
相同,并且您的 URL 以斜杠结尾,请尝试添加 URL 重写规则以简化“默认文档”处理。The "Default Document" part of IIS seems to fire a second
BeginRequest
event.If you have determined that the
Request.Path
is the same for theHttpApplication
in both event handlers and your URL ends with a slash, try adding a URL Rewrite rule to shortcut the "Default Document" processing.这很有趣。我从母版页中删除了对 CSS 文件的引用,并且在某些浏览器的
HttpModule
中得到的重复点击次数减少了(如建议的那样),但我仍然得到重复点击。我安装了 6 个浏览器,它们之间存在一些差异。作为参考,这是我插入浏览器进行测试的 URL:
default.aspx 被设置为起始页,并且确实为上述 URL 返回。我使用 HttpRequest.RawUrl 来报告用户点击的页面。具体来说,我将拆分
RawUrl
字符串并仅报告字符串数组中的最后一项(请参阅代码)。RawUrl = /BluHeron/default.aspx
)。RawUrl = /BluHeron
)。RawUrl = /BluHeron/
)。有几种方法可以准确报告有多少人访问了哪些页面。
/BluHeron
和空白)Application_BeginRequest
,似乎每次点击页面只调用一次。因此,即使数据库中的数据很差,我也可以选择获得良好的报告。我更愿意了解这里发生了什么,而不是数据库中有垃圾。
谢谢大家的观看!
This is interesting. I removed the reference to the CSS file from the master page and I'm getting fewer repeat hits in the
HttpModule
for certain browsers (as was suggested), but I'm still getting repeats. I have 6 browsers installed, and I'm getting some variation between them.For reference, this is the URL I'm plugging in to my browsers for this test:
default.aspx is set as the start page and is indeed returned for the aforementioned URL. I'm using
HttpRequest.RawUrl
for reporting which page the user hit. Specifically, I'm splitting theRawUrl
string and just reporting the last item in the array of strings (see code).RawUrl = /BluHeron/default.aspx
).RawUrl = /BluHeron
).RawUrl = /BluHeron/
).There are a couple ways I can get accurate reporting of how many people are hitting which pages.
/BluHeron
and blanks)Application_BeginRequest
in the global.asax file, which seems to consistently get called only once per page hit.So, I've got options for getting good reports even with crappy data in the database. I would prefer to understand what's going on here and not to have junk in the database.
Thanks for looking, everyone!
一种可能性是您可能没有考虑其他正在进行的请求。例如,假设您的 ASPX 页面引用了一些图像或 CSS 文件。如果这些请求通过 ASP.NET 管道,那么您的模块将被调用,并且它们将注册为命中。
另外,当您说
IHttpModule.BeginRequest
时,您的意思是在IHttpModule.Init()
中连接HttpApplication.BeginRequest
吗?如果是这样,那么我上面提到的原因可能仍然适用。One possibility is that there are other requests going on that you might not be considering. For example, let's say your ASPX page references some images or CSS files. If those requests go through the ASP.NET pipeline then your module will be called and they'll register as hits.
Also, when you say
IHttpModule.BeginRequest
, do you mean that inIHttpModule.Init()
you are hooking upHttpApplication.BeginRequest
? If so then the reason I mention above might still apply.禁用 Visual Studio 2013 及更高版本中的浏览器链接,这会导致第二个请求。
当应用程序从 Visual Studio 运行时会发生这种情况。
Disable Browser Link in Visual Studio 2013 and up, which causes the second request.
This occurs when an Application is run from Visual Studio.