代码之家  ›  专栏  ›  技术社区  ›  birdus

asp.net-ihttpmodule.beginrequest启动2x,应用程序程序_beginrequest启动1x

  •  6
  • birdus  · 技术社区  · 15 年前

    我正在运行VS2008和.NET3.5SP1。

    我想在我的asp.net应用程序的httpmodule中实现命中跟踪。很简单,我想。但是,我的httpmodule的beginrequest事件为每次页面命中触发两次。这个网站现在很简单…没有安全性,只是一点数据库工作。应该记录每页点击一行。为什么这件事要开两次枪?

    此外,ihttpmodule.beginrequest在第一次运行时(在关闭的Web浏览器中)为第一个页面命中触发的次数不同…在我为页面提供动态数据而命中数据库时为3次,对于未命中数据库的页面仅为1次。无论我是否触摸数据库,在第一个页面点击之后,它都会对每个页面触发2次。

    有趣的是,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 "";
            }
        }
    }
    
    7 回复  |  直到 8 年前
        1
  •  3
  •   Hith    13 年前

    这可能对答案来说太晚了,但对其他人可能会有用。我也面临同样的问题。为每个请求触发两次beginrequest事件。我调试了代码,发现第一个触发器用于实际的资源请求,而第二个触发器是“favicon.ico”请求的结果。在beginrequest事件开始时,对favicon.ico请求的简单检查消除了方法的第二次执行。

    public void Application_BeginRequest(object sender, EventArgs e) {
       HttpApplication app = (HttpApplication)sender;
       HttpContext ctx = app.Context;
    
       if (ctx.Request.Path == "/favicon.ico") { return; }
    
        2
  •  1
  •   birdus    15 年前

    这很有趣。我从母版页中删除了对css文件的引用,在某些浏览器的httpmodule中获得的重复点击次数减少了(正如所建议的那样),但我仍然获得了重复点击次数。我已经安装了6个浏览器,它们之间有一些变化。

    作为参考,这是我为这次测试插入浏览器的url:

    http://localhost/BluHeron

    default.aspx被设置为起始页,实际上,它将为上述url返回。我使用httprequest.rawurl来报告用户点击了哪个页面。具体地说,我正在拆分rawurl字符串,只报告字符串数组中的最后一项(参见代码)。

    • 每一个浏览器都报告达到了预期的default.aspx(rawurl=/bluheron/default.aspx)。
    • 6个浏览器中的4个也在报告bluheron(rawurl=/bluheron)。
    • 6个浏览器中的3个也在数据库中记录一个空白(rawurl=/bluheron/)。

    有两种方法可以让我准确地报告有多少人点击了哪些页面。

    1. 从数据库中只选择实际列出我的一个页面的行(忽略/bluheron和空白)
    2. 只需在global.asax文件中使用application_beginrequest(似乎每次点击页面只调用一次)
    3. 把这个弄清楚

    所以,即使数据库中有糟糕的数据,我也可以选择获得好的报告。不过,我更希望数据库中不要有垃圾,并了解这里发生了什么。

    谢谢大家看!

        3
  •  1
  •   Westley    12 年前

    很晚了,但遇到了同样的问题。在我们的例子中,是由于匿名请求首先返回401每个RFC。第二个请求验证。

        4
  •  0
  •   Eilon    15 年前

    一种可能是,还有其他的请求正在进行,您可能没有考虑。例如,假设您的aspx页面引用了一些图像或css文件。如果这些请求通过asp.net管道,那么将调用您的模块,并将它们注册为命中。

    另外,当您说ihttpmodule.beginrequest时,您的意思是在ihttpmodule.init()中连接httpapplication.beginrequest吗?如果是这样的话,我上面提到的理由可能仍然适用。

        5
  •  0
  •   artfulhacker    10 年前

    我们通过使用

    HttpContext.Current.ApplicationInstance.CompleteRequest();
    

    这可以防止你看到的两次火灾。

        6
  •  0
  •   Michael come lately PhiLho    8 年前

    iis的“默认文档”部分似乎再次启动 BeginRequest 事件。如果你确定 Request.Path 对于 HttpApplication 在事件处理程序和url都以斜线结尾的情况下,尝试添加url重写规则以简化“默认文档”处理。

        7
  •  -1
  •   Nathan Tuggy TonyLuigiC    8 年前

    禁用 Browser Link 在Visual Studio 2013及更高版本中,这将导致第二个请求。

    VS Snapshot

    从visual studio运行应用程序时会发生这种情况。