HTML Helpers For Forms In Razor Web Pages

4.64 (86 votes)

A nugget that has remained partially hidden from view within the Web Pages framework is the HtmlHelper class. Parts of this class peek out in the template sites provided in WebMatrix where validation is performed and related messages displayed, but a vast range of methods designed for rendering form inputs are often overlooked in tutorials, blog articles and books (mine included). This article provides an overview of Web Pages HTML Helpers, and digs into one or two in more detail.

There are HTML helpers for every kind of form control: check boxes, hidden fields, password boxes, radio buttons, text boxes, text areas, dropdown lists and list boxes. There is also a helper for the HTML Label element, which associates descriptive text to a form control and can provide usability improvements in certain cases. Each helper method provides a shorthand way to render valid HTML for the specific control. The following table lists the Html Helpers and maps them to their HTML counterpart:

Helper HTML Element
Html.CheckBox <input type="checkbox" />
Html.DropDownList <select></select>
Html.Hidden <input type="hidden" />
Html.Label <label for="" />
Html.ListBox <select></select> or <select multiple></select>
Html.Password <input type="password" />
Html.Radio <input type="radio" />
Html.TextArea <textarea></textarea>
Html.TextBox <input type="text" />


If you have had any exposure to ASP.NET MVC, these helpers will look familiar. However, don't be fooled - the Web Pages helpers do not always work in the same way as their MVC counterparts. For one thing, there is no concept of "model binding" in ASP.NET Web Pages (yet). For another, some of the overloads do not map to an MVC counterpart.

Most of the Web Pages HTML Helpers work in the same way to MVC, and have a similar set of overloads. The TextBox helper is a good example for illustrating the basics. Here's a list of the overloaded methods:

TextBox(String, Object)
TextBox(String, Object, IDictionary<String, Object>)
TextBox(String, Object, Object)

The first method generates an HTML text input with a name and id attribute that uses the string value passed to the method. The second does the same, but allows you to specify the value of the text box through the object parameter. The third and fourth options build on the second, but offer two different ways to pass values for other attributes (width, style, class etc) either as a dictionary, or as an anonymous object. Here's a form that illustrates how these work:

<form method="post">
    First Name: @Html.TextBox("firstname")<br />
    Last Name: @Html.TextBox("lastname", Request["lastname"])<br />
    Town: @Html.TextBox("town", Request["town"], new Dictionary<string, object>(){{ "class", "special" }})<br />
    Country: @Html.TextBox("country", Request["country"], new { size = 50 })<br /> 
    <input type="submit" />

And here's the HTML source for the rendered page:

<form method="post">
    First Name: <input id="firstname" name="firstname" type="text" value="" /><br />
    Last Name: <input id="lastname" name="lastname" type="text" value="" /><br />
    Town: <input id="town" name="town" class="special" type="text" value="" /><br />
    Country: <input id="country" name="country" size="50" type="text" value="" /><br /> 
    <input type="submit" />

Most of the other helpers feature the same set of four overloaded methods - even the Hidden field where attributes other than id, name and value seem irrelevant. The Radio and CheckBox helpers feature additional overloads that have a Boolean parameter through which you can specifiy whether the input should be checked or not. The following line of code results in a checked checkbox with the name and id of "myCheck":

@Html.CheckBox("myCheck", true)

DropDownLists and ListBoxes are a different proposition.There are eight overloads for the DropDownList and twelve overloads for the ListBox helper. Eight of the ListBox overloads result in exactly the same HTML as the eight DropDownList helper methods - an HTML select element that allows single selection. The other four ListBox overloads accept a Boolean, which if set to true, allows multiple selections. All a bit odd and unnecessary, really. And for that reason, I would recommend that you use the DropDownList helper for single selection lists, and the ListBox only for multi-selection to save yourself confusion. Doing this will make transition to MVC (should you decide to go that route) a lot easer too, because MVC doesn't feature anywhere as many overloads for the ListBox.

All of the DropDownList and ListBox helpers expect an IEnumerable<SelectListItem> to be provided. A SelectListItem has three properties: Value, Text and Selected. The Value property is used by the HTML value attribute of an option element, and is the value passed in the Request collection when the form is submitted. The Text property is displayed on screen and the Selected property determines whether the the item should be preselected. The following code shows how to construct a List<SelectListItem>, setting two of the items as Selected, and then passing that to a ListBox which allows multiple selection:

    var items = new List<SelectListItem>{
        new SelectListItem {Value = "1", Text = "Blue"},
        new SelectListItem {Value = "2", Text = "Red"},
        new SelectListItem {Value = "3", Text = "Green", Selected = true},
        new SelectListItem {Value = "4", Text = "Yellow", Selected = true},
        new SelectListItem {Value = "5", Text = "Black"}
@Html.ListBox("myListbox", items, null, 6, true)  

The overloaded helper method used here is ListBox(String, IEnumerable(SelectListItem), Object, Int32, Boolean). The next example shows how to generate a IEnumerable<SelectListItem> from a database query. This time, the collection will feature in a DropDownList and only one of the items will be set as selected - the item with a CategoryId of 4:

    var db = Database.Open("Northwind");
    var data = db.Query("SELECT CategoryId, CategoryName FROM Categories");
    var items = data.Select(i => new SelectListItem {
        Value = i.CategoryId.ToString(), 
        Text = i.CategoryName,
        Selected = i.CategoryId == 4 ? true : false
@Html.DropDownList("CategoryId", items)

The code above uses LINQ To Objects to work on the collection returned from the Database.Query method call. You don't have to use LINQ To Objects. You could simply iterate the data variable in a foreach loop, and build a collection of SelectListItems that way, but LINQ is the new foreach loop.

The final example shows a DropDownList created from the overloaded method that has the most parameters:

    var db = Database.Open("Northwind");
    var data = db.Query("SELECT CategoryId, CategoryName FROM Categories");
    var items = data.Select(i => new SelectListItem {
        Value = i.CategoryId.ToString(), 
        Text = i.CategoryName
@Html.DropDownList("CategoryId", "Please Select One", items, 4, new {@class = "special"})

This is the same database query as in the previous example, except that none of the items have their Selected property set to true. That job is left to the helper instead. The first parameter provides a name attribute as usual, and the second sets the "default text". The fourth parameter represents the value of the selected item and the final parameter sets the CSS class of the select list to "special". Notice that when using an anonymous object to specify HTML attributes, you must prefix C# keywords used as property names with an @ sign (in this case "class"). This is nothing to do with Razor, but is part of the C# language specification.


You might also like...

Date Posted:
Last Updated:
Posted by:
Total Views to date: 169231


- Len Wright

Nicely done, Mike. Accidentally rate this as a 1 instead of 5. Silly iPad.

- anwarhaque

All control code are so good I try this code next project

- Justin Reeves

Hi Mike, I have your book which I found very useful in getting started with Web Pages. One thing that I couldn't get working was the "Selected" helper. I am dynamically creating a drop down with Month & Year combo, I was to retain the selection between posts but I don't seem to be able to apply the helper to a dynamically generated DDL. None of the above seem to address this unless I'm being dumb (which may be the case!). Any help appreciated! :)

- Mike


I recommend you post a question to a forum detailing what you have done so far.

- Robby

In this example you pass a IEnumerable<SelectListItem> parameter to the helper function. Is it possible to pass a recordset parameter to a helper function ?

- Mike


The DropDownList and ListBox helpers expect an IEnumerable. I'm not sure what you mean by "recordset" but I doubt if it meets that criteria, so the answer would be No.

- Parthiban K

It's was really use full website for mee..
surly it gonna rocking:))

- deltaecho5

I am new to Razor/MVC, having only dabbled in programming as a hobby off and on as part of a fascination with computers (from IBM 370's to now). BASIC was taught to me in the 10th grade, and since then I piddle here and there in an attempt to learn code languages -from Fortran to MPM, from APL to Turbo Pascal, from VB to Visual C++, from HTML/Java to ASP/PHP and now to MVC - to keep my brain sharp. It is indeed spaghetti in my brain.

I am far from an adequate coder, and am more dangerous than intelligent when it comes to attempting some silly site project or the like.

Over and over I search the web for solutions to what turn out to be incredibly obvious to veterans (eg. "what? You don't know that 'I' comes before 'E' except after 'C' you silly stupid old man? Stay off the internet!" LOL).

Over and over, in my quest to gain some simple knowledge that MS seems to invariably leave out of it's knowledge base or doesn't explain completely, I arrive at one of your blogs/posts/articles.

Once again - you showed me something that I searched for hours in order to complete something simple that had previously escaped me, and I wanted to thank you.

Your knowledge is welcome, and your ability to put concise and clear information into my brain keeps me bookmarking your information.

Thanks. I earned my gray hairs, but I am happy that reading things you write doesn't add to them.

Cheers Mike!


- Bobbyg

Nice article. There are bugs in MVC 5 with dropdowns retaining values from other screens and preselecting them. I have found using SelectList instead of List<SelectListItem> fixes the bugs.

- Mike


This article is about the helpers found in the ASP.NET Web Pages framework. They are not the same as the ones in ASP.NET MVC, although the method names and signatures look similar in a lot of cases.

- David Banks

Thank you for helping me to code a DropDownList from a database query, but damn it was hard to find this page.
Great job!
Thanks !!

- Herp

This was really helpful in figuring out how to create a loosely-typed textbox; thank you so much for taking the time and posting this.

- Mike


Do I detect a whiff of sarcasm? If so, why?

Recent Comments

Pam 30/08/2017 11:30
In response to Sending Email in Razor Pages
Mike, RazorPages sound like a nice choice for somebody still working in ASP classic who wants to to...

Robby Robson 15/08/2017 00:43
In response to Routing in Razor Pages
Mike: great stuff. Now that .Core Standard 2.0 is formally out, how soon will you rewrite your book...

Satyabrata Mohapatra 28/07/2017 08:59
In response to Sending Email in Razor Pages
Bit off topic, but congratulation sir for your MVP award. You deserve it !!!...

Satyabrata Mohapatra 23/07/2017 16:43
In response to Razor Pages - The Elevator Pitch
@Dale Severin You can continue to build apps using web pages....

Satyabrata Mohapatra 23/07/2017 16:40
In response to Sending Email in Razor Pages
Thanks for sharing...learned a lot...

Gfw 22/07/2017 11:53
In response to Sending Email in Razor Pages
Question... Does System.Net.Mail support SSL?...

Dale Severin 20/07/2017 03:38
In response to Razor Pages - The Elevator Pitch
I work with razor web pages extensively. I appreciate the rapid development it permits me to I am as...

Obinna Okafor 14/07/2017 01:19
In response to Routing in Razor Pages
Thank you, Mike. Good post....

Satyabrata Mohapatra 11/07/2017 16:02
In response to Routing in Razor Pages
Very powerful routing system!!...

Cyrus 05/07/2017 03:41
In response to Razor Pages - Getting Started With The Preview
How can I trim packages and services as much as possible to use just razor pages? I don’t want to to...