This Question is similar but the accepted answer solves it server side, I'm interested in client side solutions.
Given this ViewModel
public class MyViewModel
{
public string ID { get; set; }
[Required(ErrorMessage = "I DEMAND YOU MAKE A CHOICE!")]
[Display(Name = "Some Choice")]
public int SomeChoice{ get; set; }
[Required(ErrorMessage = "I DEMAND YOU MAKE A CHOICE!")]
[Display(Name = "Keyword")]
public string Keyword { get; set; }
}
and the razor
<div>
@Html.LabelFor(model => model.SomeChoice, new { @class = "label" })
@Html.DropDownListFor(model => model.SomeChoice, (SelectList)ViewBag.SomeChoice, "Select...")
@Html.ValidationMessageFor(model => model.SomeChoice)
</div>
and assume ViewBag.SomeChoice contains a select list of choices
The rendered html doesn't get the data-val="true" data-val-required="I DEMAND YOU MAKE A CHOICE!" attributes in it like @Html.EditorFor(model => model.Keyword) or @Html.TextBoxFor would render.
WHY?
Adding a class = "required" to it like so
@Html.DropDownListFor(model => model.SomeChoice, (SelectList)ViewBag.SomeChoice, "Select...", new { @class = "required" })
which uses the jQuery Validation class semantics and blocks on submit but doesn't display the message. I can do this kind of thing
@Html.DropDownListFor(model => model.SomeChoice, (SelectList)ViewBag.SomeChoice, "Select...", new Dictionary<string, object> { { "data-val", "true" }, { "data-val-required", "I DEMAND YOU MAKE A CHOICE!" } })
Which will put the right attributes there, and blocks on submit and shows the message but doesn't take advantage of the RequiredAttribute ErrorMessage I have on my ViewModel
So has anyone written a DropDownListFor that behaves like the other HtmlHelpers with regard to Validation?
EDIT Here is my EXACT code
In HomeController.cs
public class MyViewModel
{
[Required(ErrorMessage = "I DEMAND YOU MAKE A CHOICE!")]
[Display(Name = "Some Choice")]
public int? SomeChoice { get; set; }
}
public ActionResult About()
{
var items = new[] { new SelectListItem { Text = "A", Value = "1" }, new SelectListItem { Text = "B", Value = "2" }, new SelectListItem { Text = "C", Value = "3" }, };
ViewBag.SomeChoice = new SelectList(items,"Value", "Text");
ViewData.Model = new MyViewModel {};
return View();
}
About.cshtml
@using Arc.Portal.Web.Host.Controllers
@model MyViewModel
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
<div>
@Html.LabelFor(model => model.SomeChoice)
@Html.DropDownListFor(model => model.SomeChoice, (SelectList)ViewBag.SomeChoice, "Select...")
@Html.ValidationMessageFor(model => model.SomeChoice)
</div>
<button type="submit">OK</button>
}
And here is the rendered code
<form action="/Home/About" method="post"> <div>
<label for="SomeChoice">Some Choice</label>
<select id="SomeChoice" name="SomeChoice"><option value="">Select...</option>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
<span class="field-validation-valid" data-valmsg-for="SomeChoice" data-valmsg-replace="true"> </span>
</div>
<button type="submit">OK</button>
</form>
It posts back to my controller...this shouldn't happen