HttpResponse.End vs HttpResponse.Закрыть против HttpResponse.SuppressContent


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

Response.End();

Это приводит к ThreadAbortException, которое является по конструкции.

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

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

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

Response.Flush();
Response.SuppressContent = true

А потом просто отпустите страницу завершите нормально.

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

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

Правка 2: Файла mypage.aspx - имеет главную страницу, которая может включать стандартный контент, верхние и нижние колонтитулы и т. д. Эта страница может просто отображаться как обычная страница. Он также может просто написать (например) XML-документ для загрузки. При написании XML-документа (определяется при загрузке страницы), он очистит выход, установит content-type to XML, записать все XML, а затем, если оставить нормально, вы в конечном итоге с остальной частью рендеринга страницы ASPX прикрепляется к концу - что, очевидно, не требуется / ломает XML.

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


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


7 33

7 ответов:

Обновление-предупреждение: есть лучший метод, не используйте его, вместо этого смотрите ответ Итана!

Я бы не сказал, что есть веская причина избегать ответа.Конец. Желание избежать затрат на ThreadAbortException, позволяя циклу запроса страницы продолжаться и заставляя его выполнять дополнительную работу, которая не является необходимой, не кажется правильным.

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

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

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

Конечный метод также находится в моем списке" никогда не использовать". Лучший способ остановить запрос-вызвать HttpApplication.CompleteRequest. Метод End существует только потому, что мы пытались быть совместимыми с классическим ASP, когда был выпущен 1.0. Классический жерех имеет ответ.Метод End, который завершает обработку сценария ASP. Чтобы имитировать такое поведение, метод end 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

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

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

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

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

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

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

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

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

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

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

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

Если вы хотите продолжить выполнение, но также замкнуть конвейер http, рассмотрите возможность использования ответа.Промыть и HttpContext.Текущий.ApplicationInstance.CompleteRequest() как ответ.End() делает это, когда контекст не находится в отменяемом периоде.

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