Publish Date: 12/2/2008
Resources Mentioned in the Show
Developers want control. Developing for the web is seemingly
more of a love/hate relationship with the tools at our disposal. Sometimes our
tools and frameworks give us power, but not control. While we love the functionality
and ease-of-use of many of the stock server controls found in ASP.NET WebForms,
sometimes we find that the underlying HTML isn’t exactly what we need.
To address the growing need for more control over web page
markup we’ve seen movements like the CSS
Control Adapters and the emergence of ASP.NET
MVC framework which give us 100% control over markup.
MVC and control adapters are not the only answer to gaining
more control. For the sea of standard WebForm applications there are many techniques
available for gaining more control.
Tame ViewState
One of the first places to exercise control over your HTML
is to reign in ViewState. ViewState was once hailed as a huge time saver upon
its introduction and now often the bedrock feature of ASP.NET is maligned for
all manner of code bloat.
The fact is, though, ViewState is not inherently evil and is
effective when used appropriately. The problem with ASP.NET is not that it
features ViewState, but that the framework is cavalier in its use of ViewState.
The problem is ViewState is turned on by default.
Consider a page that includes a data-bound ListView control
using the default ASP.NET template. The page template and all controls automatically
have ViewState enabled.
The following is a screen shot of the HTML generated by the
ListView:

Notice that the control simply renders a table. There is no
editing behavior implemented on this page therefore there is no need for
ViewState. Disabling ViewState will change the source to look like this:

Note: Surprisingly,
setting EnableViewState="false" does not get rid of ViewState entirely. If you
have a HTML form set to run-at server, then you will always have at least one
hidden control in your markup with some "ViewState" data. This data, though, is
trivial in size.
Tip: Turn off
ViewState by default and use it only when necessary. You can even turn off
ViewState globally in your application by disabling it in the web.config in the
pages element.

If you find ViewState is unavoidable in your application you may consider looking
into the options of moving it to the web server or even down to the database.
Question the Form Tag
Another foundational control in ASP.NET is the run-at server
form tag – but do you really need it?
As you just saw when working with ViewState, as long as a
server-controlled form element is on your page, extra HTML in the form of
ViewState and supporting JavaScript for post backs is emitted to the page. The
default ASP.NET page template includes a form tag on every page, but often its
presence is not necessary.
Returning to the example from the previous section, look at
the HTML generated from placing a read-only ListView in a server form with
ViewState disabled:

This page has no input controls and is simply a read-only
page so having a form on the page doesn’t really make sense.
The next screen shot is how the page looks with the form tag
removed:

Tip: Remove
server-controlled forms from your page if they are not necessary.
You may even consider removing them from your page first and
wait for the design to dictate whether or not you need a form on the page. Perhaps
you are even so bold as to edit the Visual Studio template to remove the form
tag from new pages?
The template is found under this location:
C:\Program Files\Microsoft Visual Studio
9.0\Web\WebNewFileItems\CSharp\WebForm.aspx
or
C:\Program Files\Microsoft Visual Studio
9.0\Web\WebNewFileItems\VB\WebForm.aspx
NOTE: If you edit
this file you are tinkering with Visual Studio’s default templates, which under
normal circumstances is probably a bad idea. The change suggested here, however
is pretty benign. In any event make backups - be certain of what you are doing,
and if something goes wrong don’t blame me :)
No-Markup Controls
Server controls are valuable because they create a layer of
abstraction above HTML elements. This abstraction determines how controls
render to different browser versions and save developers time from having to
write code by hand. While these benefits are realized in many situations,
sometimes server controls are just more than you need.
I have often seen developers use inappropriate controls just
to get some text on the screen or to control the visibility of controls.
The Literal Control
Do you need to render
a simple string to the page? Then don’t use a Label control unless you have
plans for the extra SPAN tags that come with the data – instead try using a
Literal control.
The Literal control’s purpose is to render a string literal
to the page – and only the string literal.
Take a look at the next two lines of ASPX code:

The controls are effectively doing the same thing: rendering
a name to the page. The resulting HTML from each of these controls is quite
different:

The Label is rendered with wrapping SPAN tags. In this case,
the control is on a page associated to a master page so the HTML bloats even
further with the unique client ID generated by the server. Often when using a
Label control developers do not use the accompanying HTML that’s rendered with
the data.
Using the Literal control, however simply renders the text
to the screen as desired.
Tip: Be aware of
when you simply need text on the page and use the appropriate controls.
Note: Take care
to not confuse the Literal control with a different control name LiteralControl.The
LiteralControl exists to aid server control construction and is rarely used
directly in code.
The Placeholder Control
Do you need to
programmatically show or hide a group of controls? Don’t just make that DIV
runat="server" or turn to a Panel control – instead try wrapping your controls
in a Placeholder control.
The Placeholder
control is a very useful control that doesn’t seem to get a lot of
attention. What makes the Placeholder useful is that the control may contain
children controls and it renders no HTML to the page.
Often Placeholders are used for template designs and other scenarios
where you don’t know which controls are needed until runtime. There are a
number of other applications for the Placeholder beyond its normal use. You can
also use this control to help control what is shown and hidden on your page.
Consider the typical scenario where a message is initially
hidden from the user, but is later displayed on the screen. A common approach
to this problem is to create a server-controlled DIV on the page and set the
Visiblity property to false:

For simple pages the markup that is rendered to the page is
exactly what you would expect, but in more practical settings the HTML gets
altered.
The next screenshot shows you how that DIV is rendered to
the page when the markup lives inside a master page:

The age-old problem of ASP.NET changing a control’s ID
creeps up. This is a problem because once you start interacting with style
sheets and JavaScript the client IDs become very important. While there are a
number of ways around this issue for both CSS and scripting, why not dodge the
problem altogether?
Instead of making the DIV a server control, wrap your
content inside a Placeholder and then you have the same programmatic control
over the block of controls without having to worry about the HTML being
affected.

You could also use the MultiView
control to accomplish this same behavior without generating any extra
markup.
Tip: Use controls
that do not generate HTML wherever appropriate.
Expressions Have No Ego
If you truly don’t need extra markup created for you –
consider skipping the use of a server control altogether and use in-line
expressions. ASP.NET MVC makes heavy use of expressions and while some think
heavy use can create messy co-mingled code – there is a good pragmatic reason
for using them.
If you use a server control, you have to have some strategy for
providing the control with data. Getting data into the control requires you to
write code in the codebehind. Writing code is not a bad practice at all – it
can just be time-consuming. Depending on where the control resides on the page
you will often have to do most if not all of these steps:
- Declaring a control in the
ASPX
- Finding the appropriate
event method in the page lifecycle to tap into
- Locating and cast the
control to the appropriate type (in some cases)
- Provide the control with
data
If you opt for using expressions instead you can simply
inject the data exactly where it need to go.
So instead of doing this:


Try doing this:


In the end you’ll find that not using server controls when
they are truly unnecessary will help tame your rendered markup significantly.
Choose Controls Wisely
One of the best ways to control the HTML that your pages
generate is to be familiar with what common controls with render. The following
tables contain an abbreviated list of ASP.NET server controls and a summary of
the type of markup they emit.
Standard Controls
| Control Name |
Renders |
| Label |
SPAN elements surrounding Text property value |
| TextBox |
HTML text input element |
| Button |
HTML button input element |
| LinkButton |
Anchor element |
| ImageButton |
Anchor and image (IMG) elements |
| HyperLink |
Anchor element |
| DropDownList |
Select element with options for values |
| ListBox |
Select element with option tags for values. (The ListBox
renders a value for the SIZE attribute allowing more than one option to
appear at a time.) |
| CheckBox |
HTML checkbox input element |
| CheckBoxList |
If RepeatLayout is set to Table, then the control renders
standard table markup with the checkbox input elements.
If RepeatLayout is set to Flow, then the control renders a
series of Label and BR elements with the checkbox input elements. |
| RadioButton |
HTML radio input element |
| RadioButtonList |
If RepeatLayout is set to Table, then the control renders
standard table markup with the radio input elements.
If RepeatLayout is set to Flow, then the control renders a
series of Label and BR elements with the radio input elements. |
| Image |
IMG element |
| ImageMap |
IMG element and MAP element |
| Table |
HTML table |
| BulletedList |
Series of LI elements inside a UL element |
| HiddenField |
HTML hidden input element |
| Literal |
N/A |
| Calendar |
Complex series of elements including links and table markup |
| AdRotator |
Anchor and image elements |
| Wizard |
Complex series of elements including links and table
markup |
| MultiView |
N/A |
| Panel |
DIV or Table element depending on the browser capabilities |
| Placeholder |
N/A |
Data Controls
| Control Name |
Renders |
| GridView |
Table element with optional anchors |
| DataList |
If RepeatLayout is set to Table, then the control renders
standard table markup
If RepeatLayout is set to Flow, then the control renders a
series of Label and BR elements |
| DetailsView |
Series of elements including links and table markup |
| FormView |
HTML table |
| Repeater |
N/A |
| ListView |
N/A |
ASP.NET SEO
Much of the talk surrounding taming HTML is often in the
context of building website to be search-engine friendly. In some arenas
ASP.NET is viewed as a sub-standard platform for creating search engine
optimized websites. While this charge is categorically false, sometimes it’s
not hard to see why some reach such an extreme conclusion.
ASP.NET is no better or worse platform for building sites
optimized for search engine placement than a Java or Rails site – the problem
is often the UI developer. While Microsoft and a host of third-party organizations
work hard building tools and controls that aid in RAD development, using these
techniques in their default states, may not always be the best approach for building
public facing websites.
The bottom line is know the HTML you are generating and use
the right tool for the right job.