HttpModule.Init - безопасно добавлять обработчик HttpApplication.BeginRequest в интегрированном режиме IIS7
Мой вопрос похож, но не идентичен:
Почему мой хост (softsyshosting.com) не поддерживает обработчики событий BeginRequest и EndRequest? (Я также читал блог mvolo, на который есть ссылки)
Цель состоит в том, чтобы успешно подключить HttpApplication.BeginRequest в событии IHttpModule.Init (или в любом месте внутри модуля), используя обычный модуль HttpModule, интегрированный через конфигурацию system.webServer, то есть тот, который не:
- вторгаться в Global.asax или
переопределить HttpApplication (модуль предназначен для автономного и многократного использования, поэтому, например, у меня есть такой конфигурационный файл):
<system.webServer> <validation validateIntegratedModeConfiguration="false"/> <modules> <remove name="TheHttpModule" /> <add name="TheHttpModule" type="Company.HttpModules.TheHttpModule" preCondition="managedHandler" />
До сих пор любая стратегия, которую я пытался подключить к HttpApplication.Regest, приводит к одной из двух причин: симптом 1 заключается в том, что BeginRequest никогда не срабатывает, или симптом 2 заключается в том, что следующее исключение возникает во всех управляемых запросах, и я не могу поймать и обработать его из кода пользователя:
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
System.Web.PipelineModuleStepContainer.GetEventCount(RequestNotification notification, Boolean isPostEvent) +30
System.Web.PipelineStepManager.ResumeSteps(Exception error) +1112
System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +113
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +616
Комментируя app.BeginRequest += new EventHandler(this.OnBeginRequest)
в init прекращается исключение конечно. Init вообще не ссылается на объекты Context или Request.
Я пытался:
- Удалены все ссылки на HttpContext.Current в любом месте проекта (все еще симптом 1)
- Протестировано удаление всего кода из тела моего метода OnBeginRequest, чтобы убедиться, что проблема не является внутренней по отношению к методу (= исключение)
- Анализировать трассировку стека и вызывать только app.BeginRequest+=..., если стек не запущен InitializeApplication (= BeginRequest не запускается)
- Только вызов app.BeginRequest + = при втором проходе через Init (= BeginRequest не запускается)
Кто-нибудь знает хороший подход? Есть ли какая-то косвенная стратегия для перехвата Application_Start внутри модуля (кажется маловероятным)? Другое событие, которое а) можно подключить к конструктору модуля или методу Init, и б) которое впоследствии является безопасным местом для подключения обработчиков событий BeginRequest?
Большое спасибо
2 ответа
Метод Init вашего HttpModule будет вызываться несколько раз одним веб-приложением (тогда как Application_Start в вашем global.asax будет вызываться только один раз для каждого AppDomain).
Инициатива действительно место для подключения к BeginRequest.
Я также столкнулся с этой ошибкой, и она была вызвана подключением к событию BeginRequest более одного раза. Я не уверен, если это ошибка в интегрированном режиме IIS 7 или нет...
Когда вы делаете app.BeginRequest, вы вызываете context.BeginRequest, используя параметр context для метода Init вашего IHttpModule, или вы вызываете HttpContext.Current.BeginRequest += ...?
У меня были те же проблемы, описанные выше. Я обнаружил, что практическим решением было всегда удалить, а затем добавить обработчик. таким образом:
public override void Init()
{
base.Init();
lock (_initialisationLockObject)
{
BeginRequest -= Global_BeginRequest;
BeginRequest += Global_BeginRequest;
}
}
Я подозреваю, что обработчики событий очищаются после одного или нескольких вызовов init. Если вы тщательно только попытаетесь добавить обработчик события в первый раз, в более поздние времена вызывается init, но не добавляется событие, и, следовательно, обработчик вообще не вызывается. Если вы не попробуете ничего хитрого, чтобы ограничить количество добавлений события, вы увидели, что получили несколько вложений. Сначала попытка удалить, а затем добавить (внутри блокировки, чтобы остановить любые грубые условия гонки), кажется, добивается цели.
Это ужасно, и мы не должны этого делать!
надеюсь, это поможет