Tips, tricks and all the info about Microsoft Visual Studio 2008

Writing your own Html Helpers for the ASP.NET MVC Framework

, posted: 23-Mar-2009 09:00

Anyone who's dipped a toe in the ASP.NET MVC Framework will have encountered Html Helpers. These remove the need to drop large chunks of code into your markup to generate common elements that can't be hard-coded by giving you the means to use small chunks of code instead. Which is better.

For example, if you have the framework scaffold a "List" view template for you, by default you'll get Edit and Details links for each item in the Model. The end result looks something like this:

OK, admit it: How many of you when you first saw this sort of thing in the MVC Framework threw up your hands, said "It's ASP all over again" and ran away screaming? Trust me, it's really not that bad. The helper methods solve the problem of producing markup from the Model or other dynamic content, and actually remove the need to inject a lot of code into the markup (which would be uncomfortably like the bad old days with ASP, at least as many people wrote it) by wrapping it up in a compact bundle.

The output generated at runtime from the fragment above is gloriously simple and uncluttered. For example:

(In this case I based my view on a PeopleController. The links will invoke the Edit and Details Actions respectively for the item with Id=1).

It needs to be stressed that these extensions are not controls: they are as their name implies helper methods that generate vanilla markup based on any arguments you supply them. They have in themselves no page lifecycle, no state and certainly no event model. In some ways they could be compared with macros.

The output of most HTML Helpers is simply a string containing markup. The same is true of course of server controls, but with HTML Helpers the markup produced is not the kind that makes View Source the stuff of nightmares. This is because generating a string of HTML is all they do, so there is no need for hidden elements or script to enable a complex relationship between the generated markup and things that happen on the server.

Additionally, because they are not controls, it follows that they are not composite controls, so you are not confronted with markup containing element ids longer than a sentence by Marcel Proust.

So how do you write your own?

First you need to have a basic understanding of Extension Methods – if you don't know what extension methods are then clearly you've wasted your life and there's nothing I can do for you (Oh come on, that was a joke, so no sulking – extension methods are defined in the Visual Studio and .NET Framework glossary this way "A static method that can be invoked by using instance method syntax. In effect, extension methods make it possible to extend existing types and constructed types with additional methods").

A typical HTML Helper is an extension method applied to the View's instance of the HtmlHelper class. Consequently if you're using C# your method signature will typically start with something like "(this HtmlHelper htmlHelper", followed by any other parameters required.

For my example I'm going to create an HTML Helper that generates a list of Technorati tags surrounded by a DIV element and preceded by the words "Technorati tags: ". Technorati tags are described here.

I'm assuming a scenario where your MVC application is something like a blog or a CMS where it is useful to have posts or articles accompanied by tags, and consequently your model will include a property such as "TagList", representing a comma-delimited list of tags (if you want anything more structured it probably makes more sense to use fixed categories).

So, our HTML Helper will need to take a Model property which for any given instance might contain something such as this: "rambling, arrant nonsense" and output HTML like this:

(I know there's more you'd probably want to include, and I'll come to that shortly).

To build the markup my first impulse was to use an HtmlTextWriter in conjunction with a StringWriter, but the TagBuilder object provided with the MVC Framework has some useful characteristics that we can take advantage of to good effect.

Here's the first version:

In this case I've used TagBuilders to create the anchor tags, aggregated the results with a StringBuilder and placed the results in the InnerHtml property of an outer TagBuilder for the DIV.

Note also that I've used the HtmHelper object's AttributeEncode and Encode methods .

The problem with the HTML this code produces (which I showed earlier) is that it is effectively sealed: if you want to apply CSS styling to it or manipulate it with jQuery you're out of luck.

We could of course supply hard-coded id and class values for the DIV, but you know in your belly (ewww...) that that's a bad idea, and it would of course mean that anyone using this helper would need to see its output or examine the code to know what element id or CSS class they should be referring to. It's much better to let the developer specify these values when they're using your helper extension.

Rather than supplying parameters for "id" and "class" and then adding others that you realise you've forgotten, there is a pattern used by the built-in helper methods that you can refer to.  So I'll overload my extension method to support two versions of an htmlAttributes parameter, one an object and the other a dictionary:

This is where the TagBuilder really comes into its own: we can use the MergeAttributes method of the TagBuilder to add attributes from the dictionary into its collection of attributes, and these are then rendered with the rest of the element.

The attributes themselves can be specified using object initaliser syntax, so (again assuming C#) I can add an id and a style to my DIV this way:

This gives us the following HTML:

But you probably don't want to use inline styles, instead you want to use a class defined in an external CSS file so designers won't snub you at parties (ignoring for now the fact that developers don't get invited to the same parties as designers). And here's where we run into one of those "Why is life never simple?" issues – "class" is a C# keyword, and is not allowed in an object initialiser in C#. Which in this particular case is a bit of a shame.

You can of course use "Class" instead, but if you're like me you'll recoil at the thought of upper case in attribute names (and justifiably worry about XHTML compliance). My solution was decidedly hacky but it works (although I addressed "class" directly rather than taking a more general approach). I threw in "_class" as well for good measure.

In this case the attribute is still specified as "Class" or even the doesn't-mean-anything "_class", but is then replaced in the TagBuilder's attribute collection by the preferred "class". You are welcome of course to use a better approach.

The end result is a TechnoratiTagList HTML Helper that not only happily generates the appropriate HTML from our tag list string but is also acceptably addressable and stylable, while still producing vanilla HTML without any bloat.

And that's nice.

The full source of the TechnoratiTagList helper can be downloaded from Skydrive.

Download Visual Studio 2008 90 day trial
For detailed information and to request a free 90-day trial DVD of Visual Studio 2008 Team Suite to be sent out to you, go to the Visual Studio webpage.

About the Author
Kevin Daly has been programming professionally for almost 22 years. He has been using .NET and C# continuously since the Beta 2 in 2001, which probably explains the bags under the eyes. Other examples of his views, rants and even the odd code sample can be found on his blog at  He will work for money.  He will now stop talking about himself in the third person because it’s frankly a bit weird.

Other related posts:
The New Zealand ALM Conference 2011 (Application Life Cycle Management)
Automating Visual Studio 2008
Windows Azure Table Storage - Getting Started - Part 2

Comment by Adam, on 23-Mar-2009 20:31

You can use

new { @class = "myclass" }

to set the class for the htmlAttributes parameter. The @ symbol escapes reserved words in c#.


About the Visual Studio 2008 Blog

In the years since the hugely successful release of Visual Studio 2005, Microsoft has used developer feedback from all over the world to introduce over 250 new features in the 2008 release.

This sponsored blog will bring Visual Studio 2008 tips and tricks from well known developers in the Australian and New Zealand tech community directly to you.

Make sure you bookmark this blog or subscribe to our RSS feed.

Other blog posts

The New Zealand ALM Conference...
Automating Visual Studio 2008...
Windows Azure Table Storage - ...
Windows Azure Table Storage - ...
XML and XSLT in Visual Studio ...
Introduction to New SQL Server...
Using the Visual Studio 2008 P...
Getting started with Windows A...
Why consider sitting for an MC...
Unit testing .Net Compact Fram...

Some recent comments

Praveen M on Visual Studio 2008 support for building SilverLigh: I installed SILVERLIGHT TOOLS for VS2008 at my work. I am able to do silverlight...

zefo on Unit testing with Visual Studio 2008: Just minor recommendation: better use *.png for the screenshots. Jpeg is more su...

gil ziny on Unit testing with Visual Studio 2008: When I associate the unit test with TFS testing policy, if fails during check-in...

lynette on Visual Studio 2008 JavaScript Debugging: i have enable in IE the ability to debug scripts. if i go to my section in my c...

Junkie on Why consider sitting for an MCTS or MCP Certificat: The way you presented the case for certification has been completely different f...

Brian Link on Unit testing with Visual Studio 2008: You seem to be incorrect in one of your opening remarks - it seems that web.conf...

Dipanwaya on Unit testing .Net Compact Framework applications w: Steps Behind the Test in the VS 2008? How to test a module in the VS 2008 Envir...

Ricardo on Visual Studio 2008 support for building SilverLigh: Yes! Found the solution myself :) Reset the environment of Visual Web Developer...

Ricardo on Visual Studio 2008 support for building SilverLigh: Have the same problem after installing Visual Web Developer 2008 SP1 and Silverl...

kjward on Automating Visual Studio 2008: thanks lots for all the great info. i'm sure the answer to my question is in th...


The Visual Studio 2008 blog is sponsored by Microsoft NZ. The blog posts are the authors' genuine accounts of their experiences with Visual Studio 2008 and are not influenced or filtered by Microsoft NZ in any way.