HTML Helpers and Forms
|
This section documents ASP.NET MVC 5.3.x, ASP.NET Web API 2.2, ASP.NET Web Pages 3, OWIN/Katana, SignalR 2,
and ASP.NET Identity 2 — all running on .NET Framework 4.8.1 — the This is not ASP.NET Core MVC. ASP.NET MVC 5 is the pre-Core, This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
This page documents ASP.NET MVC 5.3.x HTML helpers on .NET Framework 4.8.1 — not ASP.NET Core’s Tag Helpers, which replace most of this API surface (see the cross-link at the end of this page).
Four kinds of helper
-
Standard — untyped, string-keyed:
Html.TextBox("Name", value). -
Strongly typed — a lambda expression over
Model, giving compile-time checking and correctname/idattributes for model binding:Html.TextBoxFor(m ⇒ m.Name). -
Templated — resolved by type/metadata rather than naming a specific input:
Html.EditorFor(m ⇒ m.Price)(see Views, Layouts, and Partials). -
Inline (
@helper) — a markup-producing function scoped to one view (see Razor Syntax).
Strongly typed helpers are preferred in current MVC 5 code: they survive a property rename (compile error
instead of a silent broken form) and their generated name attribute is exactly what the default model binder
expects (see Model Binding and Validation).
Html.BeginForm / Html.BeginRouteForm
Both return an IDisposable (MvcForm) that writes the closing </form> tag when disposed — almost always
used with a using block:
@using (Html.BeginForm("Edit", "Products", FormMethod.Post, new { @class = "form-horizontal" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@* fields *@
<button type="submit">Save</button>
}
@using (Html.BeginRouteForm("ProductDetails", new { id = Model.Id }, FormMethod.Post))
{
@* posts to a specific named route instead of an action/controller pair *@
}
The *For field helpers
@model MyApp.Models.ProductEditViewModel
@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Name)
@Html.PasswordFor(m => m.NewPassword)
@Html.TextAreaFor(m => m.Description, 5, 40, null)
@Html.CheckBoxFor(m => m.IsActive)
@Html.RadioButtonFor(m => m.Size, "Small")
@Html.RadioButtonFor(m => m.Size, "Large")
@Html.DropDownListFor(m => m.CategoryId,
new SelectList(Model.Categories, "Id", "Name", Model.CategoryId), "-- choose --")
@Html.ListBoxFor(m => m.SelectedTagIds, new MultiSelectList(Model.AllTags, "Id", "Name"))
@Html.HiddenFor(m => m.Id)
@Html.EditorFor(m => m.Price)
@Html.DisplayFor(m => m.CreatedOn)
@Html.EnumDropDownListFor(m => m.Status) <!-- MVC 5.1+: builds a SelectList from an enum's values -->
SelectList/MultiSelectList (System.Web.Mvc) wrap an IEnumerable, a value-field name, a text-field name,
and the currently selected value(s) — constructed in the controller or the view model, not hand-built as
<option> tags.
Validation helpers
@Html.ValidationSummary(excludePropertyErrors: true, message: "Please correct the errors below.")
@Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
These render the error messages ModelState accumulated during model binding/validation (see
Model Binding and Validation) and carry the
data-val-* attributes that unobtrusive client validation reads.
Html.AntiForgeryToken()
Emits a hidden input carrying a per-user, per-session token that the matching [ValidateAntiForgeryToken]
action filter checks on submit — MVC 5’s CSRF defense; see
Security Hardening for the full mechanism and the AJAX variant.
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
HtmlHelper extension methods and MvcHtmlString
Every helper above is an extension method on HtmlHelper/HtmlHelper<TModel>, which is how custom helpers are
added without subclassing anything:
public static class CustomHtmlHelpers
{
public static MvcHtmlString StarRating(this HtmlHelper html, int rating)
{
var stars = string.Concat(Enumerable.Range(0, 5)
.Select(i => i < rating ? "★" : "☆"));
return new MvcHtmlString(stars); // marks the string as "already safe", bypassing auto-encoding
}
}
@Html.StarRating(Model.Rating)
MvcHtmlString (implementing IHtmlString) is what tells Razor a value is already-encoded markup rather than
plain text to be HTML-encoded — returning a bare string from a helper would get double-escaped when rendered.
Why ASP.NET Core replaced most of this with Tag Helpers
Two problems with HTML helpers motivated Tag Helpers: they read as C# method calls even though they produce
HTML (@Html.TextBoxFor(…) gives no visual cue in the rendered markup, and HTML/CSS tooling can’t see
through it), and building one requires C#, not markup. ASP.NET Core’s Tag Helpers
(<input asp-for="Name" />) attach to ordinary HTML attributes, stay readable as HTML in the source, and are
processed server-side without changing the tag a designer would otherwise write. See
Razor Syntax and Tag Helpers for the ASP.NET Core
equivalent of every helper on this page, and
Creating
Custom HTML Helpers (C#) for more on the MVC 5 model.
Next: Model Binding and Validation covers how a submitted form comes back into an action’s parameters.