Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

HtmlTextWriter Musings


:P
On this page:

Ok, so I’m trying to be a good ASP.NET citizen and write out my control output through the verbosity that is the HtmlTextWriter interface. All is well, but I keep running into the issue of not being able to quite figure out how to write out a <br /> tag using the proper writer code.

 

My first guess would be:

 

writer.RenderBeginTag(HtmlTextWriterTag.Br);

writer.RenderEndTag();

 

but that’s not getting the expected results:

<br>

</br>

 

The right way to do this is:

 

writer.WriteBeginTag("br");

writer.Write(HtmlTextWriter.SelfClosingTagEnd);

 

which properly generates:

 

<br />

 

But this got me thinking – isn’t this basically just like hardcoding the value as:

 

writer.Write("<br />");

 

In both cases I’m actually forcing the full <br /> tag to be explicitly written regardless of the type of output generated.

 

I’m just thinking out loud here. The reason for using the HtmlTextWriter interface over just building a string supposedly is that you can apply different rendering adapters to the output. Basically a different HtmlTextWriter can be passed and that writer potentially can interpret the more generic HtmlTextWriter syntax into adaptable Html/XHtml and potentially WAP or whatever.

 

But writing code like the above basically defeats this. Question is, what’s the right way to write this so it would be adaptive?

 

Further upon checking a little closer my pages are set up to use XHTML as the page layout schema. Yet when I checked the HtmlTextWriter type passed to my control in this case, it’s being passed as an HtmlTextWriter rather than the expected XHtmlTextWriter…

 

I haven’t looked at the details in 2.0, but how does ASP.NET decide when to use the XHtmlTextWriter? It seems it would have to look at the page in combination to the user agent in order to determine the writer to use... 

 

I was searching around regarding a few of these topics and I ran into a few interesting posts (here’s one) that try to tell you that all non-HtmlTextWriter output is evil. In many cases the point made is that adaptive rendering is not available to plain written output.

 

Duh – if you create ASPX pages that have static markup text that you yourself create on the page, no amount of adaptive rendering will help you. If you have a couple of Response.Write() statements or you use a StringBuilder to output text to a literal control, that’s hardly going to change those same dynamics…

 

While I certainly would recommend using an HtmlTextWriter when possible let’s not forget that writing the HTW code is a heck of a bit more involved that spitting out a string. It depends entirely on the scenario involved. Certainly if you build a resusable control it’s a good idea to use a HTW, but on page code that is tied to a very specific HTML schema anyway the value of using a HTW is much less obvious…


The Voices of Reason


 

DuncS
June 09, 2006

# re: HtmlTextWriter Musings

Too true Rick. If you're a control vendor - then definitely use HTW so that we have another extensibilty point in being able to Render() it using a custom, sub-classed HTW. But for the rest of rest of us: do the simplest, most easily readable/maintainable thing (eg, writer.Write("<br/>")), because inevitably: YAGNI.

AsbjornM
June 09, 2006

# re: HtmlTextWriter Musings

Reflector tells me that you have an method called WriteBreak, in both HtmlTextWriter and XHtmlTextWriter, in HtmlTextWriter it is implemented like this:

this.Write("<br />");
and in XHtmlTextWriter it is implemented like this:
this.WriteFullBeginTag("br/");

so..

Jeff Atwood
June 09, 2006

# re: HtmlTextWriter Musings

Yeah, I agree with DuncS. Do the simplest thing that works. The idea that you can flip a switch and have your controls render correctly from Lynx to Firefox is a pipe dream anyway..

Here's a good eaxmple from the comments to the cazzu post:

--
Response.write("<b>Something goes wrong<br/><textarea rows=\"5\" cols=\"40\">Some details</TextArea></b>");
--

Compared to..

--
string s = "Some details";
HtmlTextWriter mhw = new HtmlTextWriter(myStringWriter);
mhw.RenderBeginTag(HtmlTextWriterTag.B);
mhw.Write("Something goes wrong");
mhw.RenderBeginTag(HtmlTextWriterTag.Br);
mhw.RenderEndTag();
mhw.AddAttribute("rows", "5");
mhw.AddAttribute("cols", "40");
mhw.RenderBeginTag(HtmlTextWriterTag.Textarea);
mhw.Write(s);
mhw.RenderEndTag();
mhw.RenderEndTag();
ErrorMessage.Visible = true;
mhw.Flush();
myStringWriter.Flush();
--

That is just WAYYY too much code for something so simple.

Bertrand Le Roy
June 09, 2006

# re: HtmlTextWriter Musings

Errr, WriteBreak?

Steve from Pleasant Hill
June 09, 2006

# re: HtmlTextWriter Musings

"but on page code that is tied to a very specific HTML schema anyway the value of using a HTW is much less obvious…"

amen

AsbjornM
June 09, 2006

# re: HtmlTextWriter Musings

Well, He is first asking about how to write the BR, so, when looking at the used classes you will find:

public override void WriteBreak()
{
this.WriteFullBeginTag("br/");
}

Peter Bromberg
June 09, 2006

# re: HtmlTextWriter Musings

This reminds me of the old joke about the two strings that stroll up to the bar.

The first string says "I'll have a bee oksdoka/ry".

Second string says to the bartender, "Don't mind my buddy - he isn't null-terminated."

:-)

Rick Strahl
June 09, 2006

# re: HtmlTextWriter Musings

Jeff, yes that is my thinking as well. Not to mention the potential for screwing up that code and spending a significant amount of time trying to debug the nesting and all that does to the maintainability of the code <g>...

And Bertrand - yup, sometimes I don't see the forest for the trees <g>. I did miss that, but the general point still applies.

Anatoly Lubarsky
June 09, 2006

# re: HtmlTextWriter Musings

Sometimes you have to render attributes so
Write("< br />") can not be generic.

And BTW, br can also have attributes, so WriteBreak seems like silly for me, not to mention the name of the function

Bertrand Le Roy
June 10, 2006

# re: HtmlTextWriter Musings

I'm not sure I see your point actually. The textwriter approach should be used by control developers so that the control of what to render is in the hands of the page developer.
The page developer is responsible for the code of his page, and is kindly asking the controls he's using to use the right textwriter. If the controls bypass this and assume their favorite flavor of HTML, it just makes the page developer's life more difficult.

Rick Strahl
June 10, 2006

# re: HtmlTextWriter Musings

Bertrand - in my case I am actually writing code in a control - otherwise I wouldn't bother and just fire away with a StringBuilder <g>... But even in controls sometimes it's difficult to find the right combination of commands to use. Maybe <hr /> is a better example since there's no built in function for it. HTW has many overlapping methods that have very similar functionality. Truth is everytime I write HTW code I have to go dig out some code I previously wrote to jog my memory exactly how it works <s> - you know, old age is setting in. As Anatoly points out there's, uh, some inconsistency in the layout of the interface...

Obviously both methods of raw output or HTW have their place. I just seriously wonder, as Jeff pointed out, how much of the holy grail of adaptive rendering we can really expect just through the magic of HTW... I'm doing the right thing just in case, although I'm not 100% clear what it's buying me other than more code complexity.

So, anybody know when XHtmlTextWriter is used and how it actually passes this thing? In the few tests I've run on a variety of pages I can't ever see an XHtmlTextWriter passed even though the pages are? What actually triggers this writer?

Bertrand Le Roy
June 12, 2006

# re: HtmlTextWriter Musings

The XHTML text writer is only used on some devices that require a strict dialect of XHTML. It is triggered by browsercaps.
The textwriters are certainly no holy grail, just part of the things you need to get good adaptative rendering. Other important parts are browsercaps and adapters.

Coding Horror
February 21, 2007

# Coding Horror: When Object-Oriented Rendering is Too Much Code


kelasings
October 19, 2007

# re: HtmlTextWriter Musings

writer.WriteBreak(); works just great for me. :-)

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024