Несколько раз за последнее время наталкивался в форумах на вопросы, связанные с использованием HttpResponse.Flush() В связи с этим решил сделать некоторое обощение этих вопросов и представить ответы, которые мне кажуться правильными 8). Критика и замечания приветствуются.
- HttpResponse.Flush()не работает при вызове внутри обработчика события Page.Load/GridView.RowCreated/Button.Click
Вызов HttpResponse.Flush() приводит к выводу всех данных из HttpResponse.OutputStream. При условии, что есть что выводить. Если ничего туда явно не занести, то при обычном течении жизненного цикла страницы HttpResponse.OutputStream начинает заполнятся только на Page.Render. Соответственно, вызов на более ранней стадии ничего не дает, т.к. в этот момент HttpResponse.OutputStream пуст.
- Переопределять Render каждый раз, когда нужно вызвать HttpResponse.Flush(), не очень охота. Нельзя ли как-нибудь попроще?
Один из вариантов - сделать контрол-пустышку и переопределить у него Render:
[code language="C#"]
public class FlushControl : Control {
protected override void Render(HtmlTextWriter writer) {
base.Render(writer);
Page.Response.Flush();
}
}
[/code]
Если, например, добавить этот контрол в ItemTemplate репитера, то HttpResponse.Flush() будет вызываться при рендеринге каждого айтема.
- В гриде 20 строк, но значение одной из ячеек вычисляется по полсекунды на каждую. Предыдущий вариант не катит.
Панацеи, как известно, не существует. Один из вариантов - перенести вызов метода вычисления значения в Render. Перенести все это по-быстрому можно используя анонимные делегаты. Другой вариант - задейстовать AJAX и запонлять значения уже после загрузки страницы. Для этих целей неплохо подходит механизм PageMethods. Но в любом случае, постарайтесь не использовать вот это:
- Хочу отрендерить контрол прямо внутри обработчика события Page.Load/GridView.RowCreated/Button.Click
Сделать это не сложно:
[code language="C#"]
myControl.RenderControl(new HtmlTextWriter(Page.Response.Output));
Page.Response.Flush();
[/code]
Но насколько это хорошо? Во-первых, данный контрол, отрендерившись, окажется в самом вначале всей страницы. Прощай разметка. Во-вторых, если не выставить ему Visible=false либо как-то иначе отключить рендеринг, контрол отрисуется ещё раз. В-третьих, всё, что будет происходить в жизненном цикле страницы, непонятно как будет влиять на контрол. Как поведет себя ViewState, сработают ли события, как отреагируют на преждевременный рендеринг другие контролы - все это остается неизвестным.
Поэтому делать так можно только в том случае, если Вы ПОЛНОСТЬЮ взяли на себя управление рендерингом на данной странице.
- Что это за свойства HttpResponse.Buffer и HttpResponse.BufferOutput ?
Оба эти свойства (одно является оберткой другого) включают/выключают буфферизацию. Ставить им значение false надо очень осторожно, потому что, с одной стороны, страница начинает отображаться постепенно, но с другой, суммарное время отрисовки увеличивается, в некоторых случаях в десятки раз.
- Как сочетаются HttpResponse.Flush() и UpdatePanel ?
Вообще говоря, никак. При синхронном обновлении всей страницы особой разницы между UpdatePanel и обычным дивом нет. Что касается асинхронного обновления, то пересоздание панелей на клиенте начинается после того, как ответ полностью получен. Поэтому даже если никакой ошибки не будет, толку не будет тоже.