HttpModule не вызывается при каждом запросе

У меня есть модуль HTTP, который я установил на нашем сервере. Странно то, что он работает, но время от времени не выполняется. У меня есть ведение журнала, и в то время, когда оно не работает, оно не достигает кода, который регистрирует. Я ничего не вижу ни в журналах IIS, ни в средстве просмотра событий.

    namespace RedirectModule
    {
        public class RedirectModule : System.Web.IHttpModule
        {
            private const string MobileUserAgent = "MobileUserAgentCacheKey";

            private const string 

STRING_TO_FIND = "info/lps";
        private const string STRING_TO_ADD = "/mobile";


        public void Dispose()
        {
            //clean-up code here.
        }

        public void Init(HttpApplication context)
        {          
            context.BeginRequest += context_BeginRequest;
        }
        private static object sync = new object();
        private void context_BeginRequest(object sender, EventArgs e)
        {

            try
            {


                HttpContext context = HttpContext.Current;


                string url = context.Request.Url.ToString().ToLower();

                if (!url.Contains(STRING_TO_FIND) || url.Contains(STRING_TO_FIND + STRING_TO_ADD))
                    return;
                Logger.Current.Log("Starting Redirect Phase");

                if (XmlToValues.IsMobile(context.Request.ServerVariables["HTTP_USER_AGENT"],
                                       GetCachedFile(context, "Settings.xml")))
                {
                    var mobileRedirect = GetRedirectUrl(url, STRING_TO_FIND, STRING_TO_ADD);
                    if (mobileRedirect != null)
                    {
                        Logger.Current.Log("Redirect to Mobile page");
                        context.Response.Redirect(mobileRedirect);

                    }
                }
                Logger.Current.Log("Web Page");
                Logger.Current.Log("End Begin Request");
            }
            catch (Exception ex)
            {
                if (ex is ThreadAbortException)
                    return;

                Logger.Current.LogError(ex);

            }
        }


        public static string GetRedirectUrl(string url, string strToFind, string strToAdd)
        {
            try
            {
                Logger.Current.Log("Get Redirect Url ");
                int idx = url.IndexOf(strToFind) + strToFind.Length;
                return url.Substring(0, idx) + strToAdd + url.Substring(idx);
            }
            catch (Exception ex)
            {

                Logger.Current.LogError(ex);


                return null;
            }
        }



        private XmlNodeList GetCachedFile(HttpContext context, string filePath)
        {
            try
            {
                Logger.Current.Log("GetCachedFile START");
                if (context.Cache[MobileUserAgent] == null)
                {
                    context.Cache[MobileUserAgent] = XmlToValues.GetMobileUserAgents(filePath);
                    Logger.Current.Log("Add Mobile File to Cache");
                }
                return (XmlNodeList)context.Cache[MobileUserAgent];
            }
            catch (Exception ex)
            {
                Logger.Current.LogError(ex);

                return null;
            }
        }

    }
}

и мой Web.Config:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>


  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="RedirectModule" />
      <add name="RedirectModule" type="RedirectModule.RedirectModule, RedirectModule" />


    </modules>
    <handlers>
      <remove name="Redirect" />
    </handlers>
    <validation validateIntegratedModeConfiguration="false"/>
  </system.webServer>
  <system.web>
    <httpModules>
      <add name="RedirectModule" type="RedirectModule.RedirectModule, RedirectModule" />
    </httpModules>
    <compilation debug="true">    
    </compilation>
  </system.web>
</configuration>

p.s. Я убрал log4net в web.config, так как это громоздко.

Вот ссылка на проект: http://www.sendspace.com/file/w42me5

Это разметка запрашиваемой страницы, она находится в файле index.htmnl:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<!-- no cache headers -->
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="no-cache">
<meta http-equiv="Expires" content="-1">
<meta http-equiv="Cache-Control" content="no-cache">
<!-- end no cache headers -->
</head>
<body>
MOBILE
</body>
</html>

person Eitan    schedule 01.08.2012    source источник
comment
Записали ли вы URL-адрес в начале обработчика BeginRequest, чтобы убедиться, что он правильный, и вы не возвращаетесь раньше, потому что URL-адрес не содержит ожидаемых строк?   -  person Chris Taylor    schedule 05.08.2012
comment
Да, у меня есть вход в Begin_Request, и когда он работает, он регистрирует запрос. Когда это не так, он не регистрирует запрос. Я добавил try and catch для ведения журнала, чтобы он не выдавал ошибку. В журнале событий нет ничего, что указывало бы на ошибку. Я добавил теги No Cache на html-страницу, которую пытаюсь открыть   -  person Eitan    schedule 05.08.2012
comment
В тех случаях, когда ваше событие HttpModule BeginRequest не срабатывает, срабатывает ли BeginRequest в Global.asax? Вы всегда запрашиваете ASPX? Можете ли вы поделиться наценкой для запрашиваемой страницы?   -  person Chris Taylor    schedule 05.08.2012
comment
Я добавил запрашиваемую разметку внизу вопроса. Он находится в файле index.html в мобильной папке.   -  person Eitan    schedule 05.08.2012


Ответы (2)


У меня была аналогичная проблема... Попробуйте отключить кеширование в своем веб-браузере и повторите попытку. Чтобы отключить кеширование для этих запросов, вам нужно изменить заголовок ответа. Пример изменения параметра кэширования

person CodeDemen    schedule 01.08.2012
comment
Спасибо за отзыв! Я думал то же самое, я работал в режиме инкогнито в Chrome и очищал кеш в Safari, когда проверял его на мобильном телефоне. Я добавил заголовки, но все равно время от времени это не работает. - person Eitan; 01.08.2012

Похоже, вы, вероятно, попали в кеш где-то между браузером и сервером. Есть много потенциальных мест для кеша, вот несколько общих шагов, чтобы попытаться найти его:

  • Браузер. Браузер не должен запрашивать то, что он кэшировал. В этом вопросе перечислены инструменты для разных браузеров, чтобы подтвердить, что запросы отправляются.
  • Клиентский компьютер. Если запрос отправляется из браузера, у вас может быть прокси-сервер (например, Squid), возвращающий кешированные данные. Вы можете использовать Fiddler, чтобы проверить, покидает ли клиентский компьютер HTTP-запрос.
  • Сетевой прокси. Та же идея, что и у клиентского компьютера, только прокси-сервер находится на сервере где-то в вашей сети. Вам нужно будет проанализировать исходящий HTTP-трафик на прокси-сервере, чтобы определить, отправляется ли запрос или нет.
  • Веб-сервер. Ваш модуль перенаправления может обслуживать кэшированный контент, а не отображать его как новый. В этом случае он должен отображаться в ваших журналах. Добавьте вызов журнала в самое начало обработчика BeginRequest, чтобы подтвердить, действительно ли запрос поступает на ваш сервер.

Чтобы предотвратить кеширование, вы можете добавить в запрос заголовки no-cache (статья здесь):

        private void Application_EndRequest(Object source, EventArgs e) 
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            context.Response.ExpiresAbsolute = DateTime.Now.AddDays( -100 );
            context.Response.AddHeader( “pragma”, “no-cache” );
            context.Response.AddHeader( “cache-control”, “private” );
            context.Response.CacheControl = “no-cache”;
        }

ИЗМЕНИТЬ

Отладка того, какой запрос попадает на сервер

HTTP 200 в ответе говорит о том, что, скорее всего, у вас нет проблем с кешем. Чтобы подтвердить, что каждый запрос действительно поступает на сервер, попробуйте добавить журнал в свой обработчик Application_BeginRequest (в Global.asax), чтобы регистрировать каждый запрос и сравнивать его с журналом, созданным вашим context_BeginRequest в вашем HttpModule.

//In Global.asax
private void Application_BeginRequest(Object source, EventArgs e) {
    Logger.Current.Log("Request made to Application_BeginRequest")
}

//In your HttpModule
    private void context_BeginRequest(object sender, EventArgs e)
    {
        //Log before any of your other code
        Logger.Current.Log("Request made to context_BeginRequest")

        try
        {
              // your code
        }
        catch (Exception ex)
        {
            // log the exception first in case this is the problem
            Logger.Current.LogError(ex);

            if (ex is ThreadAbortException)
                return;

        }
    }

Интерпретация результатов

Проверьте свой лог после запроса, который не доходит до вашего модуля.

  • Если он ничего не показывает, запрос никогда не поступал на ваш сервер. См. выше о кешах
  • Если ваш журнал заканчивается на Запрос к Application_BeginRequest, ваш модуль не вызывается.
  • Если он заканчивается на Запрос, сделанный для context_BeginRequest, в коде модуля перед вашим регистратором есть ошибка, которая вызывает сбой при некоторых запросах. Это может быть нулевая ссылка HttpContext.Current или Request, или проблема с переполнением, или множество других вещей. Это должно быть зарегистрировано вашим оператором finally.
person just.another.programmer    schedule 05.08.2012
comment
Я добавил код, который вы разместили из предыдущего ответа. Я использовал свой iPhone с беспроводным соединением, чтобы проверить URL-адрес, и он не перенаправляется на мобильный телефон (сначала он перенаправляется, но через некоторое время перестает работать). Я добавил ведение журнала, но он не достигает журнала, который находится в Begin_request. Я также добавил код мобильного перенаправления в файл global.asax, просто чтобы быть уверенным, и он все еще даже не достигает кода регистрации в функции Begin_request. - person Eitan; 05.08.2012
comment
Вы можете посмотреть на этом сайте: blogs.esri.com/esri/supportcenter/2011/12/06/ для получения инструкций по использованию Fiddler с iPhone. Убедитесь, что ваш iPhone генерирует запрос. Если это не так, то это действительно больше вопрос о том, почему iPhone не следует директивам кеша. (Вы также должны подтвердить, что исходный ответ, который вы получаете, имеет правильно установленные заголовки кеша). - person just.another.programmer; 05.08.2012
comment
Заголовки кеша есть. Я запрашиваю простой файл .html. Так что скрипач не покажет мне, что я вызываю модуль HTTP. Это ДЕЙСТВИТЕЛЬНО показывает мне, что я запрашиваю страницу. Могу кинуть ссылку на проект, это: sendspace.com/file/w42me5 - person Eitan; 05.08.2012
comment
Я также использовал инструменты Safari Developer и скрипач на своем компьютере для разработки, запросы попадают туда. Я жестко запрограммировал эти http-заголовки на html-странице: ‹!-- без заголовков кеша --› ‹meta http-equiv=Pragma content=no-cache› ‹meta http-equiv=no-cache› ‹meta http-equiv= Expires content=-1› ‹meta http-equiv=Cache-Control content=no-cache› ‹!-- end no cache headers --› - person Eitan; 05.08.2012
comment
Что вы имеете в виду, что запросы попадают туда? Вы видите запрос, покидающий ваш компьютер (через инструменты разработчика и Fiddler), и он никогда не поступает на ваш сервер? Если да, то настроен ли в вашей сети прокси-сервер, который может перехватывать/кэшировать страницу? Каковы заголовки ответа на эти загадочные запросы? - person just.another.programmer; 06.08.2012
comment
Я вижу запросы, поступающие на сервер, т.е. я получаю 200 на странице, но модуль HTTP не вызывается, нет никакого ведения журнала. Я бы подумал, что модуль HTTP не работает, но он постоянно работает для первых нескольких запросов, а затем внезапно перестает работать, и когда он не работает, нет никакого ведения журнала. Я использую log4Net, и он регистрируется, когда я нажимаю функцию Begin_Request. - person Eitan; 06.08.2012
comment
Посмотрите мои правки, давайте посмотрим, сможем ли мы точно отследить, как далеко зашел запрос. - person just.another.programmer; 06.08.2012
comment
хорошо, я поместил журнал в global.asax и в begin_request обработчика http. Он регистрируется несколько раз, но затем прекращает регистрацию. Когда я открыл средство просмотра событий, он не показывает никаких ошибок. Когда он прекращает ведение журнала, он также прекращает перенаправление. Система находится на двух серверах с балансировщиком нагрузки, может ли это быть причиной проблемы? - person Eitan; 06.08.2012
comment
давайте продолжим это обсуждение в чате - person just.another.programmer; 06.08.2012