Does your Help need Help?
By Martin Schaeferle | August 15, 2012
Writing a ton of HTML code to support almost any kind of application, particularly one that maintains data, can be breathtakingly tedious. You'll need to pepper the view with code nuggets, snippets of code embedded in the view to read from and write to the view's model and perhaps ViewData. Although it is simpler and more efficient to write this kind of code in MVC and ASP.NET than it was in classic ASP, it is still tedious.
It would be nice if Microsoft were to provide a middle ground, a feature that retains for the developer a high degree of control over the HTML, but lessens the tedium of writing reams of HTML code and makes intelligent decisions about the HTML to emit. A middle ground between the two extremes would be nice! Fortunately, they did. (Bet you saw that coming!)
The feature is called HTML helpers, or just helpers or helper methods. These are methods in the framework that emit markup for the most common HTML elements, and help create wellformed, valid markup. In this article we'll discuss the different types of HTML helper methods used in MVC.
Types of HTML Helper Methods
MVC includes three broad classes of HTML helper methods: untyped helper methods, strongly-typed helper methods, and templated helpers. The untyped helper methods first appeared in the initial release of MVC, version 1, and generally take a string with the name of the property to which it is bound at runtime. The following code is an example of using a regular HTML helper to display a label, text box, and validation message to edit a Name property of the view model object, using the Label, TextBox, and ValidationMessage helper methods.
<div class="editor-label"> @Html.Label("Name") </div> <div class="editor-field"> @Html.TextBox("Name") @Html.ValidationMessage("Name") </div>
A strongly-typed helper has "For" appended to the name of the method and takes a lambda expression that binds the helper to a model property at design time. This is in contrast to a regular helper that takes a string parameter. Strongly-typed helpers have the benefit of catching many kinds of problems at compile time instead of runtime, and IntelliSense fully supports them when you write code.
The following code is an example of using strongly-typed helpers for the same Name property of the previous code, using the LabelFor, TextBoxFor, and ValidationMessageFor methods. Notice that each takes a lambda expression to bind the helper at design time.
<div class="editor-label"> @Html.LabelFor(model => model.Name) </div> <div class="editor-field"> @Html.TextBoxFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name) </div>
Using a lambda expression lets you pass both the field that the helper is binding to and the value of the field. The strongly-typed helper method uses this information to intelligently determine how to display the data. It really is a rather elegant way to pass the information to the helper method.
TIP: Try misspelling a field name to see what happens. Specifically, misspell one of the field names in one of the TextBox helper methods in the Edit view of the DogApp project, such as changing "Age" to "Ag." You'll find that when you edit a dog's data any existing age doesn't appear, and when you save the data it stores it as zero, no matter what you put in the text box. Code that uses strongly-typed methods looks a bit more complex and requires more typing than the untyped versions, but only a little. And because the fields you are using are strongly typed, IntelliSense can help you where it couldn't with just strings, as shown in Figure 1. Another benefit of using strongly-typed helper methods is that refactoring tools can update the views if you change field names.
Figure 1. IntelliSense provides a list of the properties of the Dog object.
Templated helpers take the methods to an entirely different level, using built-in and custom templates to give you fine control over the HTML generated based on various templates. You can even throw an entire custom object at a templated helper, and the helper will use reflection to render all its properties-including nested properties-based on the templates defined for each data type, and reverting to a text box for any data types for which it has no template. The following code is an example of using a template helper to edit an entire view model, not just a single property of the object, using the EditorForModel method.
For the most part, you'll want to avoid using untyped helpers because they rely on string parameters and so tend to be error prone. Whenever you can, let MVC, Visual Studio, and the language compiler help you write good quality code!