Member-only story
Create a custom MVC Dropdownlist with custom option attributes and retain the validation.
3 min readMar 18, 2025
Step 1. Make sure to reference jquery validation in _ValidationScriptsPartial or inside _Layout.cshtml
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"></script>
Step 2. Create a custom SelectListItem and HTML helper
public class CustomSelectListItem : SelectListItem
{
public IDictionary<string, string> HtmlAttributes { get; set; }
}
public static class HtmlHelpers
{
public static IHtmlContent CustomDropDownListFor<TModel, TProperty>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<CustomSelectListItem> customSelectList,
string optionLabel,
object htmlAttributes)
{
// Create a <select> element
var selectBuilder = new TagBuilder("select");
// Add attributes like id and name
var expressionName = htmlHelper.NameFor(expression).ToString();
selectBuilder.Attributes.Add("id", expressionName);
selectBuilder.Attributes.Add("name", expressionName);
selectBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
// Add the default optionLabel (placeholder) if provided
if (!string.IsNullOrEmpty(optionLabel))
{
var optionTag = new TagBuilder("option");
optionTag.InnerHtml.AppendHtml(optionLabel);
optionTag.Attributes.Add("value", "");
selectBuilder.InnerHtml.AppendHtml(optionTag);
}
// Add <option> elements from customSelectList
foreach (var item in customSelectList)
{
var optionTag = new TagBuilder("option");
optionTag.Attributes.Add("value", item.Value);
optionTag.InnerHtml.AppendHtml(item.Text);
// Add custom attributes
foreach (var attribute in item.HtmlAttributes)
optionTag.Attributes.Add(attribute.Key, attribute.Value ?? string.Empty);
if (item.Selected)
optionTag.Attributes.Add("selected", "selected");
selectBuilder.InnerHtml.AppendHtml(optionTag);
}…