HTML Helpers
How ASP.NET MVC pages generate HTML for the browser
October 30, 2009
CoreCoder
LANGUAGES: C#
ASP.NET VERSIONS: 3.5 | MVC
HTML Helpers
How ASP.NET MVC pages generate HTML for the browser
By Dino Esposito
Any web page is made of an HTML string thatbrowsers interpret and render graphically. Source code for a static web pageconsists of plain HTML literals. A dynamic web page, which goes through asecond layer of abstraction, typically is written in an intermediate markuplanguage that some runtime environment translates into plain HTML. For example,ASP.NET web pages are written in a made-to-measure markup language saved toASPX files. The syntax of the ASPX markup language allows you to include HTMLliterals, along with comments and references to ASP.NET server controls.
ASP.NET server controls are ad hoc components thatare instantiated on the server and, when properly configured eitherdeclaratively or programmatically, end up emitting plain HTML for the browser. AnASP.NET server control is not simply an HTML generator. An ASP.NET server controlparticipates in the whole page lifecycle and is notified of any lifecycle eventsuch as Init, Load and PreRender that occurs at the page level. In addition, aserver control can fire its own events to the container page. Many servercontrols only fire events that contain the logic for a postback event. Forexample, the Button control fires the Click event to the host page. By handlingthe button's Click event, the page author can execute any logic related to theuser's clicking. In addition, ASP.NET server controls take advantage of thepage's viewstate and use it to persist their own internal state acrosssuccessive requests.
ASP.NET server controls are one of the primaryaspects that characterize the ASP.NET Web Forms model. Earlier this spring, Microsoftreleased ASP.NET MVC 1.0 a new ASP.NET programming framework that I've covered widelyin this column. Unlike Web Forms, ASP.NET MVC has a completely decoupled viewengine that acts as a plain HTML generator. Each ASP.NET MVC application isallowed to use a view engine of choice and can employ any sort of syntax toexpress the requested shape of HTML.
The standard view engine of an ASP.NET MVCapplication is still based on a subset of the Web Forms rendering engine. Thismeans that you can still use ASP.NET server controls, but only as HTMLgenerators, with no support for postback events and viewstate. In version 1.0,ASP.NET MVC doesn't formalize a rich model for components capable of producingHTML. However, as long as you employ the default view engine you can rely onHTML helpers. Let's find out more.
What's an HTML Helper, Anyway?
The typical view of an ASP.NET MVC application thatuses the default rendering engine is an ASPX file made of HTML literals, codeblocks and, optionally, server controls. The final goal of the file is to bethe template for the HTML to return to the browser. In code blocks, you canhave any .NET executable code that does any required calculation and outputsexpected HTML.
How would you output, say, an HTML input elementwith some of the attributes set to calculated values? In classic ASP.NET, youwould use a TextBox control and set (or have set) corresponding propertiesprogrammatically. A TextBox control is still a valid option in ASP.NET MVC;however, it is more of a workaround than a direct, clean solution.
ASP.NET MVC is designed to give page authors totalcontrol over any generated HTML literals. The TextBox, as well as any otherserver control, is sort of a black box whose generated HTML cannot be fullycontrolled. An HTML helper is a static method on a system class that outputs anHTML string based on the provided input data. In a way, an HTML helper is asimplified and lightweight version of an ASP.NET server control tailor-made forASP.NET MVC. An HTML helper has no viewstate, no postbacks, no page lifecycleand events; it consists of a standard HTML template that is filled with customdata.
Standard HTML Helpers
A number of predefined HTML helpers are includedwith the ASP.NET MVC framework. You can use them to emit the markup for themost common elements, including text boxes, drop-down lists, links and forms.You won't find anything to render more sophisticated pieces of HTML such astables, grids and pagers. However, the extensibility of the framework triggereda number of open-source projects aimed at making additional HTML helpersavailable. You'll find custom HTML helpers at www.codeplex.com/MVCContrib.
At the end of the day, an HTML helper is just anextension method created for the system-provided System.web.Mvc.HtmlHelperclass. Figure 1 shows the typical implementation of an HTML helper that rendersa check box.
public static string CheckBox(this HtmlHelper htmlHelper, stringname, bool isChecked)
{
returnhtmlHelper.CheckBox(name, isChecked, null);
}
Figure1: Implementation of a CheckBox helper
As you can see, the helper adds a new method named CheckBoxto the system's HtmlHelper class. The CheckBox method receives a few argumentsthat will be used internally to generate an appropriate HTML string. In thesample code (Listing 1), the HTML helper receives the name of the check box anda Boolean value indicating whether or not the element is checked. The followingfragment illustrates how to use the check box helper in the view of an ASP.NETMVC page:
<% =Html.CheckBox("CheckBox1", true) %>
The HTML output in the page will look like the following:
Figure 2 lists the predefined HTML helpers availablein ASP.NET MVC.
Helper | Type | Description |
---|---|---|
CheckBox | Input | Returns the HTML string for a check box input element |
Hidden | Input | Returns the HTML string for a hidden input element |
Password | Input | Returns the HTML string for a password input element |
RadioButton | Input | Returns the HTML string for a radio button input element |
TextBox | Input | Returns the HTML string for a text input element |
BeginForm | Form | Returns a MvcForm object that represents a HTML form |
EndForm | Form | Void method, closes the pending tag |
ActionLink | Link | Returns the HTML string for an HTML link |
DropDownList | Select | Returns the HTML string for a drop-down list |
ListBox | Select | Returns the HTML string for a list box |
TextArea | TextArea | Returns the HTML string for a text area |
ValidationMessage | Validation | Returns the HTML string for a validation message |
ValidationSummary | Validation | Returns the HTML string for a validation summary message |
RenderPartial | User controls | Returns the HTML incorporated in a user control |
Figure2: Predefined HTML helpers
Feeding HTML Helpers
Although an HTML helper is a fairly simplecomponent, it still incorporates some logic. The helper logic is fed by methodparameters. Each helper method has its own set of parameters based on theexpected behavior. The CheckBox helper accepts two parameters the name of thecheck box and its checked status. The CheckBox helper counts the followingoverloads:
public static string CheckBox(this HtmlHelper htmlHelper,
string name);
public static string CheckBox(this HtmlHelper htmlHelper,
string name, boolisChecked);
public static string CheckBox(this HtmlHelper htmlHelper,
string name,IDictionary htmlAttributes);
public static string CheckBox(this HtmlHelper htmlHelper,
string name, objecthtmlAttributes);
public static string CheckBox(this HtmlHelper htmlHelper,
string name, boolisChecked, IDictionary htmlAttributes);
In addition to specific parameters, you canconfigure all HTML helpers using an explicit list of HTML attributes. Any attributesin the list will appear in the rendered markup for the element. You canindicate HTML attributes in either of two ways via a dictionary or an object.The dictionary is a key/value collection where the key indicates the name ofthe HTML attribute. You can express the value through any .NET object. The realvalue saved in the markup, though, is whatever string expression comes out ofthe Convert.ToString function applied to the value.
You also can store HTML attributes in a custom .NETobject. In this case, values are retrieved via reflection by looking at thepublic properties of the custom object. Names of public properties should matchHTML attributes for the target HTML element. Typically, you choose this optionwhen you want to use an object initializer, as follows:
<% = Html.CheckBox("CheckBox1", new { @checked="checked",value="on"} )%>
Because in C# checked is a recognized keyword, you'rerequired to prefix it with @ to instruct the compiler to ignore that instanceof the string. The preceding code results in a check box that is checked andhas a value of "on."
A check box is just a button with no syntax elementto specify a descriptive text and a check box without an attached label is nothelpful. In ASP.NET Web Forms, the CheckBox control silently emits a tag that is filled with the value of the Text property. InASP.NET MVC, predefined HTML helpers offer no support for labels. To render acheck box with some associated text, you need the following:
<% = Html.CheckBox("CheckBox1") %>
Check me
Adding the tag is up to you. But thecompanion label tag for a check box is a great exercise as you start playingaround with custom HTML helpers. (I'll touch on custom HTML helpers nextmonth.)
Finally, HTML helpers are tightly coupled with someASP.NET MVC data containers such as ViewData. Suppose your view contains thefollowing:
<% = Html.CheckBox("CheckBox1") %>
And suppose also that the controller's method that triggersthe view adds an item to ViewData with a matching ID.
public ActionResult About()
{
ViewData["CheckBox1"]= "true";
return View();
}
In this case, the check box is rendered in a checkedstate as set in ViewData.
More on the CheckBox Helper
The CheckBox HTML helper deserves mention of apeculiarity that often goes unnoticed. When you invoke CheckBox(), the helperdoesn't render only an element; it alsoemits a hidden input element with the same ID as the check box, as Figure 3shows.
Figure 3:The real output of the CheckBox HTML helper
More interestingly, the hidden input element, exceptfor the ID, has a fixed layout (see example below).That is, for every checkbox a hidden element is generated with an ID that matchesthe ID of the checkbox. Besides the ID, the structure of the hidden input fieldalways looks the same, regardless of the attributes of the check box.
What's the purpose of this element? Check boxelements work differently from most HTML input elements. When browsers post thecontent of a form, only check boxes that are currently checked are appended tothe body of the request. In particular, a key is added to the body that equalsthe name of the input element and a value is added that matches the valueproperty of the element. A check box that is unchecked is ignored during thepost stage. In ASP.NET Web Forms, the IsChecked property of the CheckBoxcontrol contains all the logic to handle the selection of the element. InASP.NET MVC, adding a hidden text box makes it easier to determine whether acheck box was originally included in the page that was unchecked when the postoccurred.
What happens when you use Request.Form["CheckBox1"]from either the controller or a view's code block? If the check box wasunchecked, then Request.Form["CheckBox1"] references the hidden fieldand returns false. If the check box was checked, then Request.Form["CheckBox1"]returns the string "true,false." It's up to you to parse the stringand ensure it contains the substring "true."
However, if you're using the default model binder,and binding to a complex object like an Order, then the "true,false"string is resolved for you by the binder. Otherwise, either you do your ownparsing or switch back to an old-style but equally effective and manual markup. Using the default bindermeans you have a controller method such as the following:
public ActionResult Save(Order order)
{
if (order.IsConfirmed)
ViewData["Status"]= "Confirmed";
else
ViewData["Status"]= "[Being processed]";
return View();
}
The default binder simply creates an instance of the Orderclass where properties are mapped to any posted data that matches the pattern parameter.PropertyName. In other words,the parameter "order" receives data from any input element namedorder.PropertyName, such as order.IsConfirmed.
<% = Html.CheckBox("order.IsConfirmed")%>
I'll cover model binders in a future column.
Simple Help
HTML helpers are plain markup generators that savedevelopers some work in the creation of web views. Like classic ASP.NET servercontrols, HTML helpers incorporate some logic and produce HTML as a result.Like classic ASP.NET server controls, HTML helpers offer a simplifiedprogramming interface for developers. However, HTML helpers are much simplerthan server controls. They have no event model and generate no viewstate. Inthis article, I examined the general characteristics of helpers and focused onone of them the CheckBox helper. In an upcoming column, I'll cover otherpredefined helpers and show how to create custom HTML helpers. Stay tuned!
Dino Esposito ([email protected])is an architect at IDesign and specializes mainly in ASP.NET, AJAX and RIAsolutions. Dino co-authored the best-seller Microsoft.NET: Architecting Applications for the Enterprise (Microsoft Press, 2008)and the just-released twin book MicrosoftASP.NET and AJAX: Architecting web Applications (Microsoft Press, 2009).
About the Author
You May Also Like