Html Helpers vs Server controls

Posted on December 8, 2009 by Frederik Vig in ASP.NET

I received some very good comments on my post Extending PageData with some cool Html Helpers. Which made me want to explain my thoughts on the subject a bit more :).

For me, most of the server controls abstract away to much of the details, that I feel we as web developers should be comfortable with, and want to have full control over. Server controls make use of viewstate, affecting both performance and increasing the size of the page. Many render old deprecated HTML markup, make it hard to work with ids in CSS and JavaScript, and have a complex life cycle.

I know there are ways to fix some of these issues (turn off viewstate, control adapters etc). But I feel that the added work load when using server controls, and trying to fix them, is higher than the benefit we get. With Html Helper, I type so much less code than before, and I have full control. I can easily add my own extension methods for stuff that I use a lot, I’ve one place to go to update the code. Combined with Page Type Builder I have intellisense of all my code, I can refactor the code without worrying about breaking it. Instead of having to check for runtime errors I can compile my .aspx/.ascx and be sure that I haven’t added a typo.

A little comparison

Lets say we are tasked with implementing this simple list.

<h3>Recent Articles</h3>
 
<div class="block odd">
 
	<a title="" href="index.html"><img src="images/thumb-1.jpg" class="thumbnail" alt="img" width="240px" height="100px"/></a>
 
	<div class="blk-top">
		<h4><a href="index.html">Aliquam Risus Justo Lorem Ipsum Dolor Sit Amet</a></h4>	
		<p><span class="datetime">August 27, 2009</span><a href="index.html" class="comment">2 Comments</a></p>		
	</div>						
 
	<div class="blk-content">
		<p>
		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec libero. Suspendisse bibendum. 
		Cras id urna. Morbi tincidunt, orci ac convallis aliquam, lectus turpis varius lorem, eu 
		posuere nunc justo tempus leo. Donec mattis, purus nec placerat bibendum, dui pede condimentum 
		odio, ac blandit ante orci ut diam. Cras fringilla magna. Phasellus suscipit, leo a pharetra 
		condimentum, lorem tellus eleifend magna, eget fringilla velit magna id neque. 				
		</p>					
 
		<p><a class="more" href="index.html">continue reading &raquo;</a></p>
	</div>
</div>
 
<div class="block even">
 
	<a title="" href="index.html"><img src="images/thumb-2.jpg" class="thumbnail" alt="img" width="240px" height="100px"/></a>
 
	<div class="blk-top">
		<h4><a href="index.html">Aliquam Risus Justo</a></h4>	
		<p><span class="datetime">August 26, 2009</span> <a href="index.html" class="comment">2 Comments</a></p>
	</div>						
 
	<div class="blk-content">
		<p>
		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec libero. Suspendisse bibendum. 
		Cras id urna. Morbi tincidunt, orci ac convallis aliquam, lectus turpis varius lorem, eu 
		posuere nunc justo tempus leo. Donec mattis, purus nec placerat bibendum, dui pede condimentum 
		odio, ac blandit ante orci ut diam. Cras fringilla magna. Phasellus suscipit, leo a pharetra 
		condimentum, lorem tellus eleifend magna, eget fringilla velit magna id neque. 	
 
		<a class="more" href="index.html">continue reading &raquo;</a>			
		</p>
	</div>
 
</div>
 
<div class="fix"></div>
...

We might implement this by using a Repeater control, and a user control with the news story.

<h3>Recent Articles</h3>
<asp:Repeater runat="server" ID="rptNewsList">
<ItemTemplate>
    <div class="block odd">
	<Jungle:NewsStory runat="server" NewsPage="<%# Container.DataItem %>" />
    </div>
</ItemTemplate>
<AlternatingItemTemplate>
    <div class="block even">
	<Jungle:NewsStory runat="server" NewsPage="<%# Container.DataItem %>" />
    </div>
    <div class="fix">
    </div>
</AlternatingItemTemplate>
</asp:Repeater>

The NewsStory user control might look like this when using Html helper methods.

<a href="<%= NewsPage.LinkURL %>">
    <%= NewsPage.HtmlImage("ListImage", "PageName") %>
</a>
<div class="blk-top">
    <h4><%= NewsPage.HtmlLink() %></h4>
    <p><span class="datetime"><%= NewsPage.StartPublish.ToString("dd MMMM yyyy")%></span></p>
</div>
<div class="blk-content">
    <p><%= NewsPage.PreviewText(200) %>
        <a class="more" href="<%= NewsPage.LinkURL %>">continue reading &raquo;</a>
    </p>
</div>

For me this code is very easy to change and update. It is very readable (for me HTML markup describe the meaning of the content and give it context). I can easily add ids where I need. Update the markup without having to change my code-behind (and compile). If I need to change some of the logic I have one extension method to update, not a bunch of code-behind files to go to.

By using server controls it might look something like this.

<asp:HyperLink runat="server" ID="lnkListImage" />
<div class="blk-top">
    <h4><EPiServer:Property runat="server" PropertyName="PageLink" ID="heading" /></h4>
    <p><asp:Label runat="server" CssClass="datetime" ID="lblDate" /></p>
</div>
<div class="blk-content">
    <p><asp:Literal runat="server" ID="ltlPreviewText" />
        <asp:HyperLink runat="server" ID="lnkReadMore" CssClass="more" Text="continue reading &raquo;" />
    </p>
</div>

And the code-behind.

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
 
    this.lnkListImage.ImageUrl = this.NewsPage["ListImage"] as string ?? string.Empty;
    this.lnkListImage.Text = this.NewsPage.PageName;
    this.lnkListImage.NavigateUrl = this.NewsPage.LinkURL;
 
    this.heading.PageLink = this.NewsPage.PageLink;
 
    this.lblDate.Text = this.NewsPage.StartPublish.ToString("dd MMMM yyyy");
 
    this.ltlPreviewText.Text = Helper.PreviewText(this.NewsPage, 200);
 
    this.lnkReadMore.NavigateUrl = this.NewsPage.LinkURL;
}

They both do the same thing, and at this point it really is just about what you prefer. But, (for me at least) those extra lines of repetitive code get quite boring to type after a while. There are of course possibilities to have a bunch of helper classes that generate these server controls for you, and then just add them to the various control collections. But why go to all that problem, when a simple extension method in most cases does a much better job?

What do I use? Both. I use what makes the most sense there and then. Server controls are here to help me as a developer, same with extension methods, they are here to help me. When I come to the point that I have to use a lot of hacks and fixes to make something work, I stop, take another look at my solution, and try to use a different approach instead. I feel we’ve reached a point where we need to fix/hack to much to make server controls work. That might be why my most used server control is the Repeater and recently the ListView :).

Related Posts: