Использование HtmlTextWriter для рендеринга серверных элементов управления? - PullRequest
5 голосов
/ 29 января 2009

Я пишу RenderContents() метод управления сервером ASP.NET. Метод использует объект HtmlTextWriter для визуализации содержимого вывода. Для элемента управления, который я пишу, использование методов HtmlTextWriter похоже на то, что для открытия и закрытия каждого тега и добавления каждого атрибута в поток потребуется много строк кода. В конце я чувствую, что в итоге получу код, который намного длиннее, чем нужно.

Я думал, что если бы я использовал цепочечный класс, такой как StringBuilder, мой код стал бы намного чище и легче для написания.

Мне было интересно, есть ли причина использовать объект HtmlTextWriter для визуализации всего содержимого моего элемента управления? Помимо проверок безопасности (я предполагаю) это включает в себя, чтобы убедиться, что вы не пишете теги в неправильном порядке или создаете недопустимую разметку, я не вижу причины.

Кажется, было бы проще сделать что-то вроде этого:

protected override void RenderContents(HtmlTextWriter output)
{
    StringBuilder s = new StringBuilder();
    s.Append("lots")
     .Append("of")
     .Append("strings");

    output.BeginRender();
    output.Write(s.ToString());
    output.EndRender();
}

Есть ли причина, по которой это было бы плохой идеей?

Обновление
В ответ на Mehrdad Afshari ответ:
Я не особо задумывался о требованиях к памяти для создания отдельного StringBuilder объекта. Как насчет создания обертки для HtmlTextWriter, чтобы ее можно было объединить в цепочку, чтобы лишняя строка не была создана.

public class ChainedHtmlTextWriter
{
    private HtmlTextWriter _W;
    public ChainedHtmlTextWriter(HtmlTextWriter writer)
    {
        _W = writer;
    }

    public ChainedHtmlTextWriter Write<T>(T value) 
    { 
        _W.Write(value); 
        return this; 
    }

    public ChainedHtmlTextWriter WriteLine<T>(T value)
    {
        _W.WriteLine(value);
        return this;
    }
}

Ответы [ 3 ]

10 голосов
/ 29 января 2009

Я работаю над приложением, в котором разработчики пошли по ужасному пути, который вы изучаете. Это восходит к тем дням, когда вам приходилось писать собственные библиотеки ISAPI, которые выплевывали HTML-код. Это постоянная головная боль для работы. Если ваш код в основном строковый, значит что-то не так.

Большую часть кода этого типа, который я меняю, я создаю экземпляры серверных объектов, настраиваю их свойства по своему желанию, а затем передаю их .RenderControl (writer). Это значительно облегчает чтение и работу с кодом. Если это приводит к снижению производительности из-за накладных расходов, я готов принять их (на самом деле, после того, как я внес изменения, приложение обычно работает быстрее, так что, как это ни странно, это не так, но я не профилировал) мой код).

Одним простым недостатком жесткого кодирования ваших вещей в строках является изменение стандартов HTML. Код, над которым я работаю, был написан в 04/05 году, и с тех пор
стал
, а html-теги в верхнем регистре больше не кошерны и т. Д. Если они использовали серверные элементы управления, эти серверные элементы управления изменили свои выводит html без необходимости что-либо делать. Это всего лишь один простой пример.

РЕДАКТИРОВАТЬ: Да, и между прочим, BeginRender и EndRender не имеют никакой реализации. Они являются заполнителями, которые вы можете переопределить и предоставить пользовательские функции в классе, производном от HtmlTextWriter.

EDIT2: иногда немного обременительно всегда использовать серверные элементы управления, например, для контейнеров и прочего. Я буду делать много .Controls.Add (), а затем визуализировать контейнер позже. Поэтому иногда я делаю это:

writer.AddAttribute(HtmlTextWriterAttribute.Class, "myContainerClass");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
// do some stuff, .RenderControl on some other controls, etc.
writer.RenderEndTag();

Как уже упоминалось, это отобразит правильный html, даже если html div изменится в будущем, потому что у меня нет жестко закодированных строк.

4 голосов
/ 29 января 2009

С точки зрения производительности, для этого потребуется больше копий строк. HtmlTextWriter пишет напрямую в выходной буфер. StringBuilder, с другой стороны, имеет свой собственный буфер. Когда вы вызываете ToString для StringBuilder, необходимо создать новую строку, а затем она будет записана в выходной буфер с помощью output.Write. Требуется гораздо больше работы.

1 голос
/ 29 января 2009

Не думаю, что вам следует вызывать BeginRender / EndRender, это делается на странице.

Я не вижу, как использование строителя строк могло бы спасти любую работу, используя собственные методы HtmlTextWriters.

...