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

HttpResponse.End vs HttpResponse.Close vs HttpResponse.SuppressContent

Внутри ASPX-страницы я хочу закончить ответ в определенных точках (не из-за ошибки), в зависимости от пути кода, так что больше ничего не будет отправлено обратно по потоку. Естественно используется:

Response.End();

Это приводит к возникновению ThreadAbortException, которое по дизайну.

Следующее, похоже, работает, но не похоже на правильный подход в соответствии с этим вопросом SO:

Response.Flush();
Response.Close();

Итак, как насчет этого?

Response.Flush();
Response.SuppressContent = true

а затем просто запустите страницу как обычно.

Я мог бы просто обработать и усвоить ThreadAbortException, но я просто хочу узнать, есть ли что-то неправильное /gotchas с подходом SuppressContent?

Edit: Чтобы дать немного больше примера. Скажем, у меня есть страница ASPX, в которой я могу изменить тип контента на один из нескольких вариантов. В зависимости от типа содержимого и сценария в данной точке кода я хочу предотвратить отправку большего количества контента клиенту. Предположим, что после того, как параметр SuppressContent установлен в значение true, нет проблемы с дальнейшим запуском на стороне сервера. Я просто не хочу, чтобы что-то еще было отправлено клиенту.

Изменить 2: MyPage.aspx - имеет главную страницу, которая может включать стандартное содержимое, заголовки, нижние колонтитулы и т.д. Эта страница может просто отображаться как обычная страница. Он также может просто выписать (например) XML-документ для загрузки. Если вы выписываете XML-документ (определенный при загрузке страницы), он очищает вывод, устанавливает тип содержимого в XML, записывает весь XML-выход, а затем, если он оставлен в обычном режиме, вы получаете остальную часть страницы ASPX-рендеринга, являющейся привязана к концу - это, очевидно, не требуется/ломает XML.

Изменить 3: На данный момент я использую метод SuppressContent. Чтобы попытаться довести этот вопрос до конца, я повышаю щедрость и ставит вопрос другим путем: когда вы должны использовать SuppressContent? Почему вы использовали его вместо Response.End?


Пожалуйста, ознакомьтесь с приведенным ниже ответом на решение, которое я на самом деле закончил, поскольку в итоге я нашел способ избежать исключения ThreadAbortException при использовании Response.End. Я уже не ответил на этот вопрос.


4b9b3361

Ответ 1

update - предупреждение: есть лучший метод, не используйте его, вместо этого см. ответ "Этан".

Я бы не сказал, что есть веская причина, чтобы избежать Response.End. Желая избежать затрат на ThreadAbortException, разрешив цикл запроса страницы, и у вас есть дополнительная работа, которая не нужна, кажется неправильной.

ThreadAbortException - особый тип исключения, предназначенный для остановки потока от выполнения (его автоматически отбрасывается, даже если он пойман). Тем не менее, есть некоторые сценарии, где это может нанести вред (см. Содержимое сообщества, добавленное в конце ThreadAbortException).

Если вы не находитесь в одном из этих сценариев, вы должны придерживаться Response.End. Обратите внимание, что некоторые способы использования, делают SuppressContent и Response.End, я думаю, в случаях, когда вы хотите избежать некоторых вещей, которые будут поступать из внутреннего Response.Flush.

Ответ 2

Я знаю, что это старый вопрос, но я включаю это в интересах любого, кто может наткнуться на этот пост. Я искал ошибку, которая привела меня к рассмотрению моего использования Response.End и обнаружила сообщение MSDN через год после этого вопроса, который можно было бы суммировать как " Никогда, никогда не используйте Response.End". Вот о чем говорит Томас Марквардт, проектировавший Integrated Pipeline для IIS7:

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

Из http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx

Ответ 3

В итоге я нашел простое решение для использования Response.End() без получения исключения ThreadAbortException.

Response.Flush();
Response.End();

Из моего первоначального вопроса я всегда пытался JUST Response.End() после отправки некоторого контента в поток ответов.

Похоже, что если вы выполняете Response.End(), то вы получаете исключение ThreadAbortException. Делая Флаш сразу перед Конец, исключение ThreadAbortException фактически не бросается.

Кажется, работает отлично - теперь ThreadAbortException бросает сейчас, когда я использую Response.End

Ответ 4

Это очень распространенный вопрос. И почти всегда бывает ошибкой называть что-либо кроме Response.End(). Ниже приведено описание End() из MSDN:

Отсылает весь текущий буферизированный вывод клиенту, останавливает выполнение страницы и вызывает событие EndRequest.

Это похоже на то, что вы хотите сделать. И вы заметите в последней части, что оно вызывает событие EndRequest. Это означает, что после вызова End() все данные очищаются клиентом, который был написан до конца(), сокет закрыт, а ресурсы освобождены, и ваша программа немедленно прекратит обработку запроса.

Ответ 5

Что делать, если после вызова Response.SuppressContent = true ваша страница будет вносить изменения в запись в базе данных?

Ответ 6

Насколько я понимаю код, отражающий HttpResponse, используя подход Flush/SuppressContent, вы будете уязвимы для кода, пытающегося сделать изменения заголовка после флеша. Изменение заголовка после флеша даст HttpException.

Я бы использовал Response.End(), чтобы быть абсолютно уверенным, что ничто другое не может помешать отклику.

Если вы хотите продолжить выполнение, но также и короткое замыкание, то http-конвейер рассматривает использование Response.Flush() и HttpContext.Current.ApplicationInstance.CompleteRequest() как Response.End(), когда контекст не находится в периоде отмены.

Ответ 7

Вы уверены, что стратегия дизайна верна? Какую предварительную обработку вы можете сделать, чтобы обеспечить отправку правильных заголовков, а затем придерживаться ее до тех пор, пока script не выполнит свои задачи?