Как определить, запущен ли Page_PreRender? - PullRequest
1 голос
/ 19 мая 2011

Я запускаю метод в переопределенной Page OnUnload, но только если запущен метод Page_PreRender.

Очевидно, что я могу перевернуть bool уровня класса, когда нахожусь в Page_PreRender, и проверить его в OnUnload, но если есть более естественный способ узнать, что Page_PreRender запустился, я бы хотел использовать это.

Есть идеи?

Спасибо за любые мысли.

ОБНОВЛЕНИЕ: Позвольте мне немного перефразировать мой вопрос. Я ищу ответ на вопрос о том, существует ли простой способ, свойственный жизненному циклу страницы, возможно, свойство, которое задается фреймворком ASP.Net, возможно, что-то еще, которое отличается после запуска Page_PreRender по сравнению с тем, когда Page_PreRender имеет не беги.

В настоящее время я устанавливаю логическое значение в Page_PreRender, чтобы сообщить мне, запущено ли оно. Это работает, но мне не нравится это решение, если есть способ выполнить то же самое без добавления дополнительной логической проверки. Создание события, которое происходит во время Page_PreRender, - это тот же уровень избыточности, которого я хотел бы избежать, если это возможно.

Ответы [ 7 ]

3 голосов
/ 28 мая 2011

Вы упоминаете (в своих комментариях к другому сообщению), что ваша проблема проявляется при вызове 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 :

Метод «Конец» также включен в мои «никогда использовать »список. Лучший способ остановить просьба позвонить HttpApplication.CompleteRequest. Конечный метод только там, потому что мы пытался быть совместимым с классическим ASP, когда 1.0 был выпущен. классический ASP имеет метод Response.End, который прекращает обработку ASP скрипт. Чтобы подражать этому поведению, Метод End в ASP.NET пытается поднять ThreadAbortException. Если это успешно, вызывающий поток будет прервано (очень дорого, не подходит для производительность) и конвейер будет перейти к событию EndRequest. ThreadAbortException, если успешное, конечно, означает, что поток раскручивается прежде, чем он сможет вызвать больше кода, поэтому вызов End означает, что вы после этого не буду звонить ни на какой код. Если метод End не может поднять ThreadAbortException, это будет вместо этого сбросьте ответные байты клиент, но это делает это синхронно, что очень плохо для производительность и когда пользовательский код после завершения End, конвейер прыгает вперед к EndRequest уведомление. Запись байтов в клиент очень дорогая операция, особенно если клиент на полпути по всему миру и используя 56k модем, поэтому лучше отправлять байты асинхронно, что мы и делаем когда запрос заканчивается обычным способом. Промывка синхронно действительно плохо. Подводя итог, вы не должны использовать Конец, но использование CompleteRequest прекрасно. Документация для Конец должен заявить, что CompleteRequest это лучший способ перейти к Уведомление EndRequest и завершено запрос.

Я добавил эту строку после вызова Response.Redirect (), как предлагает MSDN, и заметил, что все работает одинаково. Не уверен, что это нужно с 4.0, но я не думаю, что это больно:

HttpContext.Current.ApplicationInstance.CompleteRequest();

Обновление 1

Using "false" в вызове Response.Redirect () избегает исключения ThreadAbortException, но как насчет других необработанных исключений, которые могут быть сгенерированы на вашей странице?Эти исключения по-прежнему будут вызывать проблему вызова OnUnload () без OnPreRender ().Вы можете использовать флаг в OnPreRender (), поскольку все предлагают избежать этого, но если вы выбрасываете необработанные исключения, у вас возникают большие проблемы, и в любом случае вам следует перенаправить на страницу с ошибкой.Поскольку необработанные исключения - это не то, что вы планируете выдавать при каждой обратной передаче, было бы лучше, если бы вы включили логику OnUnload () в Try-Catch.Если вы регистрируете и отслеживаете свои исключения, вы увидите, что необработанное исключение было сгенерировано прямо перед регистрацией исключения NullReference в событии 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 () все равно будет выполняться, поэтому не стоит беспокоиться.

1 голос
/ 31 мая 2011

Ответ: да, можно, но не всегда :) Согласно коду Reflection, класс ScriptManager содержит приватное поле bool _preRenderCompleted, которое установлено на true при обработке внутреннего события IPage interface PagePreRenderComplete. Вы можете использовать Reflection, чтобы получить это поле из ScriptManager.GetCurrent(page) результирующего объекта

0 голосов
/ 28 мая 2011

Я не думаю, что хранится какое-либо состояние, потому что движок ASP.NET на самом деле не нуждается в этом, поскольку он косвенно знает свое состояние.

При поиске в .NET Reflector создается впечатление, что события рендеринга страницы вызываются из этого внутреннего метода System.Web.UI.Page:

private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint)

Вы можете взглянуть на это, нет понятия государства. Единственная информация, которую вы можете получить - это трассировка. Если у вас есть доступ к событию Unload, то у вас должен быть доступ к трассировке? или я что то пропускаю: -)

Поскольку трассировка на самом деле представляет собой набор данных, охватывающий нижнюю часть (см. Мой ответ здесь: Запись данных в Trace.axd в текстовый / xml-файл ), возможно, вы могли бы получить информацию. Но хотя параметр trace = true не рекомендуется использовать в производстве ...

0 голосов
/ 24 мая 2011

Создайте пользовательское событие, которое запускается в событии PreRender.

0 голосов
/ 24 мая 2011

Установите логическое поле в обработчике событий PreRender, затем проверьте, было ли оно установлено в обработчике событий Unload.

0 голосов
/ 19 мая 2011

Добавить трассировку = true в директиву страницы.

0 голосов
/ 19 мая 2011

Я не уверен, что именно вы подразумеваете под этим.В соответствии с ASP.NET Page Lifecycle PreRender всегда запускается до Unload.Если вы выполняете какое-то условие if внутри этого события PreRender и хотите в Unload проверить, было ли условие выполнено, логическое поле в классе страницы кажется хорошей идеей.

...