IHttpModule.BeginRequest стрельбы 2X, Application_BeginRequest стрельбы 1X - PullRequest
6 голосов
/ 02 февраля 2010

Я использую VS 2008 и .NET 3.5 SP1.

Я хочу реализовать отслеживание попаданий в HttpModule в моем приложении ASP.NET. Довольно просто, подумал я. Тем не менее, событие BeginRequest моего HttpModule запускается дважды при каждом попадании на страницу. Сайт сейчас очень прост ... нет безопасности, просто немного работы с базой данных. Должен регистрировать одну строку на страницу попадания. Почему это событие запускается дважды?

Более того, IHttpModule.BeginRequest фактически запускает другое число раз для первого обращения к странице при первом запуске (из закрытого веб-браузера) ... 3 раза, когда я нажимаю на БД, чтобы предоставить динамические данные страница, и только 1 раз для страниц, где БД не поражена. Она срабатывает 2 раза за каждую страницу, попавшую после первой, независимо от того, касаюсь я БД или нет.

Интересно отметить, что Application_BeginRequestGlobal.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 ]

3 голосов
/ 19 августа 2011

Это может быть слишком поздно для ответа, но может быть полезно для кого-то еще.Я столкнулся с той же проблемой.Событие 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; }
1 голос
/ 16 декабря 2016

Часть IIS «Документ по умолчанию», похоже, запускает второе BeginRequest событие. Если вы определили, что Request.Path одинаково для HttpApplication в обоих обработчиках событий, а ваш URL заканчивается косой чертой, попробуйте добавить правило перезаписи URL, чтобы ускорить обработку «Документ по умолчанию».

1 голос
/ 09 августа 2012

довольно поздно по этому поводу, но столкнулся с той же проблемой. В нашем случае это был первый анонимный запрос, который возвращает 401 в RFC. Второй запрос аутентифицируется.

1 голос
/ 04 февраля 2010

Это интересно. Я удалил ссылку на файл CSS с главной страницы и получаю меньше повторных обращений в модуле HttpModule для определенных браузеров (как было предложено), но я все еще получаю повторы. У меня установлено 6 браузеров, и я вижу некоторые различия между ними.

Для справки, это URL, который я подключаю к своим браузерам для этого теста:

http://localhost/BluHeron

default.aspx устанавливается в качестве стартовой страницы и фактически возвращается для вышеупомянутого URL. Я использую HttpRequest.RawUrl для сообщения о том, какую страницу посетил пользователь. В частности, я разбиваю строку RawUrl и просто сообщаю о последнем элементе в массиве строк (см. Код).

  • Каждый браузер сообщает о том, что он работает с default.aspx, как и ожидалось (RawUrl = /BluHeron/default.aspx).
  • 4 из 6 браузеров также сообщают о BluHeron (RawUrl = /BluHeron).
  • 3 из 6 браузеров также записывают пробел в базе данных (RawUrl = /BluHeron/).

Есть несколько способов получения точных отчетов о том, сколько людей посещают какие страницы.

  1. выбрать из базы данных только те строки, которые фактически перечисляют одну из моих страниц (игнорировать / BluHeron и пробелы)
  2. Просто используйте Application_BeginRequest в файле global.asax (который, кажется, постоянно вызывается только один раз за посещение страницы)
  3. Получите это выяснил

Итак, у меня есть варианты для получения хороших отчетов даже с дрянными данными в базе данных. Я, однако, предпочел бы не иметь мусор в базе данных, и понять, что здесь происходит.

Спасибо всем за внимание!

0 голосов
/ 18 апреля 2017

Отключить Ссылка на браузер в Visual Studio 2013 и выше, что вызывает второй запрос.

VS Snapshot

Это происходит, когда приложение запускается из Visual Studio.

0 голосов
/ 01 ноября 2014

Мы решили это с помощью

HttpContext.Current.ApplicationInstance.CompleteRequest();

Это должно предотвратить двойной огонь, который вы видите.

0 голосов
/ 02 февраля 2010

Одна возможность состоит в том, что существуют другие запросы, которые вы, возможно, не рассматриваете. Например, допустим, что ваша страница ASPX ссылается на некоторые изображения или файлы CSS. Если эти запросы проходят через конвейер ASP.NET, то будет вызван ваш модуль, и они будут зарегистрированы как обращения.

Кроме того, когда вы говорите IHttpModule.BeginRequest, вы подразумеваете, что в IHttpModule.Init () вы подключаете HttpApplication.BeginRequest? Если это так, то причина, о которой я упоминал выше, все еще может иметь место.

...