Вы упоминаете (в своих комментариях к другому сообщению), что ваша проблема проявляется при вызове Response.Redirect(), потому что он вызывает исключение ThreadAbortException, что приводит к тому, что ваше событие OnPreRender() не вызывается. Так почему бы не использовать это вместо этого?:
Response.Redirect("~/SomePage.aspx", false);
«Ложь», которую вы там видите, указывает, должно ли выполнение страницы прекратиться прямо здесь и сейчас. По умолчанию Response.Redirect() использует "true". Если вам нужно, чтобы ваше событие OnPreRender() запускалось так, чтобы ваше событие OnLoad() имело все, что ему нужно, установите для него значение «false» и просто убедитесь, что вы либо переходите в конец вашего Page_Load() после вызова Response.Redirect () или что код, который будет выполняться после того, как его можно запустить.
Возможно, вам не нравится идея передачи «false» с помощью перегруженного метода Response.Redirect(), поэтому вы не пошли по этому пути. Вот некоторая документация, которая может помочь вам изменить свое мнение:
Microsoft заявляет, что «рекомендуется передавать false для параметра endResponse», поскольку указание «true» вызывает метод HttpResponse.End() для исходного запроса, который затем создает исключение ThreadAbortException. когда он завершится. Далее Microsoft заявляет, что «это исключение отрицательно влияет на производительность веб-приложений». См. здесь, в разделе «Примечания»: http://msdn.microsoft.com/en-us/library/a8wa7sdt.aspx
Это было опубликовано в прошлом году на MSDN:
Метод End также находится в моем списке «никогда не использовать». Лучший способ остановить запрос — вызвать HttpApplication.CompleteRequest. Метод End существует только потому, что мы пытались обеспечить совместимость с классическим ASP, когда была выпущена версия 1.0. Классический ASP имеет метод Response.End, который завершает обработку сценария ASP. Чтобы имитировать такое поведение, метод End ASP.NET пытается вызвать исключение ThreadAbortException. В случае успеха вызывающий поток будет прерван (очень затратно, плохо для производительности), и конвейер перейдет к событию EndRequest. ThreadAbortException, в случае успеха, конечно, означает, что поток завершается до того, как он сможет вызвать какой-либо другой код, поэтому вызов End означает, что после этого вы не будете вызывать какой-либо код. Если метод End не может сгенерировать исключение ThreadAbortException, он вместо этого сбрасывает байты ответа клиенту, но делает это синхронно, что очень плохо для производительности, и когда пользовательский код после End выполняется, конвейер перескакивает вперед к уведомлению EndRequest. Запись байтов клиенту — очень затратная операция, особенно если клиент находится на полпути к миру и использует модем 56k, поэтому лучше отправлять байты асинхронно, что мы и делаем, когда запрос завершается обычным образом. Синхронная промывка - это очень плохо. Таким образом, вы не должны использовать End, но вполне можете использовать CompleteRequest. В документации для End должно быть указано, что CompleteRequest — это лучший способ пропустить уведомление EndRequest и выполнить запрос.
Я добавил эту строку после вызова Response.Redirect(), как предлагает MSDN, и заметил, что все работает одинаково. Не уверен, что это нужно с 4.0, но я не думаю, что это повредит:
HttpContext.Current.ApplicationInstance.CompleteRequest();
Обновление 1
Использование «false» в вызове Response.Redirect() позволяет избежать ThreadAbortException, но как насчет других необработанных исключений, которые могут возникнуть на вашей странице? Эти исключения по-прежнему будут вызывать вашу проблему с вызовом OnUnload() без OnPreRender(). Вы можете использовать флаг в OnPreRender(), поскольку все предлагают избежать этого, но если вы выбрасываете необработанные исключения, у вас большие проблемы, и в любом случае вы должны перенаправлять на страницу с ошибкой. Поскольку необработанные исключения — это не то, что вы планируете создавать при каждой обратной передаче, было бы лучше, если бы вы обернули свою логику OnUnload() в Try-Catch. Если вы регистрируете и отслеживаете свои исключения, вы увидите, что необработанное исключение было выдано прямо перед регистрацией исключения NullReference Exception в событии OnUnload(), и будете знать, какое из них игнорировать. Поскольку у вашего OnUnload() будет Try-Catch, он будет безопасно продолжать обработку остальной части страницы, чтобы вы могли перенаправить на страницу с ошибкой, как и ожидалось.
Обновление 2
Вы по-прежнему должны иметь свой OnUnload(), завернутый в Try-Catch, но я думаю, что это то, что вы действительно ищете (помните, что IsRequestBeingRedirected будет истинным при вызове Response.Redirect или при перенаправлении на страницу ошибки после необработанного исключения) .:
if (HttpContext.Current.Response.IsRequestBeingRedirected != true)
{
//You're custom OnUnload() logic here.
}
Благодаря этому вы узнаете, безопасно ли (и даже стоит ли) обрабатывать вашу пользовательскую логику в событии OnUnload(). Я понимаю, что, вероятно, мне следовало начать с этого, но я думаю, что сегодня мы многому научились. ;)
ПРИМЕЧАНИЕ. Использование Server.Transfer() также вызовет ужасный Response.End(). Чтобы избежать этого, используйте Server.Execute() с атрибутом preserveForm, для которого установлено значение «false»:
Server.Execute("~/SomePage.aspx", false);
return;
ПРИМЕЧАНИЕ. Что касается Server.Execute("~/SomePage.aspx", false); заключается в том, что IsRequestBeingRedirected будет ложным, но ваш OnPreRender() все равно будет выполняться, так что не беспокойтесь.
person
MikeTeeVee
schedule
28.05.2011