Подтвердить что ты не робот

Почему мой вложенный обработчик событий HttpModule EndRequest не запускается?

У меня странное поведение, когда я пытаюсь изменить свои заголовки с помощью EndRequest событий EndRequest во вложенном HttpModule на MVC 5.2.2 и .NET 4.6.2. Если я не EndRequest в моем EndRequest верхнего уровня, то HttpModule, что обработчик событий во вложенном HttpModule никогда не запускается, хотя я знаю, что Init был вызван во вложенном HttpModule.

Мой вопрос заключается в том, что происходит в моем коде ниже, чтобы заголовок "TestNested" не появлялся в заголовках ответа, если я не включил закомментированный код, который добавляет EndRequest события EndRequest, который ничего не делает?


Динамически зарегистрировать мой HttpModule верхнего уровня

[assembly: PreApplicationStartMethod(typeof(PreApplicationStartClass), "Start")]
namespace MyNamespace
{
    public class PreApplicationStartClass
    {
        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(TopHttpModule));
        }
    }
}

Вызовите Init на всех моих других HttpModules с одного модуля верхнего уровня

namespace MyNamespace
{
    public class TopHttpModule: IHttpModule
    {
        private readonly Lazy<IEnumerable<IHttpModule>> _modules = 
            new Lazy<IEnumerable<IHttpModule>>(RetrieveModules);

        private static IEnumerable<IHttpModule> RetrieveModules()
        {
            return DependencyResolver.Current.GetServices<IHttpModule>();
        }

        public void Init(HttpApplication context)
        {
            var modules = _modules.Value;
            foreach (var module in modules
                .Where(module => module.GetType() != typeof(TopHttpModule)))
            {
                module.Init(context);
            }

            context.BeginRequest += (sender, e) =>
            {
                var app = sender as HttpApplication;
                if (app != null)
                {
                    //This shows that NestedHttpModule was found
                    app.Context.Response.Headers.Add(
                        "TestModules",
                        string.Join(",", modules.Select(_ => _.GetType().ToString())));
                }
            };

            //Add this and the NestedHttpModule EndRequest handler works
            //context.EndRequest += (sender, e) =>
            //{
            //    //Do Nothing
            //};
        }

        public void Dispose()
        {
            var modules = _modules.Value;
            foreach (var disposable in modules
                .Where(disposable => disposable.GetType() != typeof(TopHttpModule)))
            {
                disposable.Dispose();
            }
        }
    }
}

Изменить некоторую информацию заголовка в обработчике события EndRequest

namespace MyNamespace
{
    public class NestedHttpModule: IHttpModule
    {
        public void Init(HttpApplication context)
        {
            //This gets called whether or not the TopHttpModule modifies context.EndRequest 
            MvcHandler.DisableMvcResponseHeader = true;

            context.EndRequest += Application_EndRequest;
        }

        public void Application_EndRequest(object sender, EventArgs e)
        {
            var app = sender as HttpApplication;
            if (app != null && app.Context != null)
            {
                //This doesn't appear to be called unless TopHttpModule modifies context.EndRequest
                app.Context.Response.Headers.Add("TestNested", "Found");
            }
        }

        public void Dispose()
        {
            //Do Nothing
        }
    }
}
4b9b3361

Ответ 1

В конвейере запросов может быть много модулей и обработчиков для изменения или настройки заголовков и другого содержимого ответа. Web.config - это лучшее место, чтобы увидеть, какой другой модуль/обработчик вызывается в течение жизненного цикла запроса. Когда вы явно завершаете запрос, он останавливает обработку остальных модулей/обработчиков, так что вы получаете значения в заголовках ответа, имеет смысл?

Ответ 2

Вы можете использовать Context.ApplicationInstance.CompleteRequest(). Это работает хорошо