Model Binded Custom HTML Helper for C# MVC

In Programming & Software Support by Jhong Regalado,
posted 4 years ago and was modified 4 years ago

In this tutorial, I am going to show you how to create a Custom HTML Helper and bind it with your view model. At this point, I assume that you are already familiar with C# MVC, and you already know how it works. Our goal for today is to create a simple dropdown menu with "yes" and "no" options in it. This dropdown might not be the exact one you need but the principles on how to do it is the same

This is the actual output of our page

/CustomHtmlBooleanDropdownListFor.png

Create a class. In my case, I created a "Helpers" folder and put this class inside it. The "htmlHelper" parameter indicates that our method inside our class is an extension of HtmlHelper class. This will allow us to add a new definition in IHTMLHelper class. The "expression" parameter is where we bind our model. The "htmlAttributes " parameter is where we put our class names, styles, custom ID or whatever attributes we can put inside our tag. In this case, we are going to use the <SELECT></SELECT> tag. Use "ExpressionHelper.GetExpressionText(expression)" to retrieve the value of the model. We use TagBuilder to create our HTML code. This function will return "MvcHtmlString"

public static class CustomHtmlHelper 
    {
        public static MvcHtmlString BooleanDropdownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
        {
            var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

            TagBuilder tag = new TagBuilder("select");
            tag.MergeAttribute("id", ExpressionHelper.GetExpressionText(expression));
            tag.MergeAttribute("name", ExpressionHelper.GetExpressionText(expression));
            tag.MergeAttributes(new RouteValueDictionary(htmlAttributes));


            TagBuilder tagOpt = new TagBuilder("option");
            tagOpt.MergeAttribute("value", "true");

            if ((bool)metadata.Model)
                tagOpt.MergeAttribute("selected", "selected");
            
            tagOpt.InnerHtml += "Yes";
            tag.InnerHtml += tagOpt;

            tagOpt = new TagBuilder("option");
            tagOpt.MergeAttribute("value", "false");
            
            if (!(bool)metadata.Model)
                tagOpt.MergeAttribute("selected", "selected");

            tagOpt.InnerHtml += "No";
            tag.InnerHtml += tagOpt;

            return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
        }
    }

We can call our Custom HTML Helper in our views using this code: "@Html.BooleanDropdownList(x=>x.IsPublic)". The helper can only be accessible if we are going to reference it in our Views. Use "@using MyApplication.Web.Helpers" to reference our views.

@model MyApplication.Web.Models.MyModel
@using MyApplication.Web.Helpers

@using (Html.BeginForm(null, null, FormMethod.Post)) {
     <div class="row mt-3">
          <div class="col">
               @Html.LabelFor(x => x.IsPublic)
               @Html.BooleanDropdownListFor(x=>x.IsPublic, new {  @class="form-control" })
               @Html.ValidationMessageFor(x => x.IsPublic, "", new { @class = "text-danger" })
          </div>
     </div>
}

Build the application, and this will be the actual result of our code in the browser. 

<div class="col">
     <label for="IsPublic">Public</label>
          <select class="form-control" id="IsPublic" name="IsPublic">
               <option selected="selected" value="true">Yes</option>
               <option value="false">No</option>
          </select>
     <span class="field-validation-valid text-danger" data-valmsg-for="IsPublic" data-valmsg-replace="true"></span>
</div>

That's all, hope it helps

Back To Programming & Software Support