I find myself repeating this code block too often...
<div class="form-group">
<div class="col-sm-3 control-label">
@Html.LabelFor(m => m.Name)
</div>
<div class="col-sm-9">
@Html.TextBoxFor(m => m.Name, null, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Name)
</div>
</div>
I have been attempting to create a MvcHtmlString custom extension, but it assumes that the @Html.LabelFor commands are text and that is what is displayed.
EDIT: Thanks Joe and Stephen!! That's what I was missing.
Here's the final answer for my code block
static MvcHtmlString BaseFieldFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, string>> expression, MvcHtmlString innerHtml, string style = null) {
var labelDiv = new TagBuilder("div");
labelDiv.AddCssClass("col-sm-3 control-label");
labelDiv.InnerHtml += helper.LabelFor(expression, new {
htmlAttributes = new { @class = "form-control" }
});
var textDiv = new TagBuilder("div");
textDiv.AddCssClass("col-md-9");
textDiv.InnerHtml += innerHtml;
textDiv.InnerHtml += helper.ValidationMessageFor(expression);
var groupDiv = new TagBuilder("div");
groupDiv.AddCssClass("form-group");
groupDiv.InnerHtml += labelDiv;
groupDiv.InnerHtml += textDiv;
return new MvcHtmlString(groupDiv.ToString(TagRenderMode.Normal));
}
and for usage
public static MvcHtmlString FieldFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, string>> expression, string style = null) {
var innerHtml = helper.TextBoxFor(expression, null, new { @class = "form-control", style });
return BaseFieldFor(helper, expression, innerHtml, style);
}
public static MvcHtmlString DropDownListFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, string>> expression, IEnumerable<SelectListItem> list, string style = null){
var innerHtml = helper.DropDownListFor(expression, new SelectList(list, "Value", "Text"), new { @class = "form-control", style });
return BaseFieldFor(helper, expression, innerHtml, style);
}
And now I can use it simply!
<div class="panel-body form-horizontal">
@Html.FieldFor(m => m.Name)
@Html.FieldFor(m => m.Address1)
@Html.FieldFor(m => m.Address2)
@Html.FieldFor(m => m.City)
@Html.DropDownListFor(m => m.State, AllowableValues.StateList, "max-width: 200px;")
@Html.FieldFor(m => m.PostalCode, "max-width: 150px;")
@Html.FieldFor(m => m.Phone, "max-width: 150px;")
</div>
Your helper needs to use the inbuilt helper methods for generating your html. For example
Refer this example for creating a helper that outputs similar html including the label, textbox and validation message.
You're not able to invoke the HTML helpers in the manner that you're trying to do so. All it will do is treat it as text out output the result as you've already seen.
Instead you need to reference the HTML helper along the lines of this: