I have the following property in my model:
[Required]
[Range(1, int.MaxValue, ErrorMessage = "Bad number")]
public virtual int Number { get; set; }
I am filling it in Controller:
List<SelectListItem> items = new List<SelectListItem>();
// numbers is just a list with entities with an integer field Number
items.AddRange(numbers.
Select(n => new SelectListItem() { Text = n.Number.ToString(), Value = n.Number.ToString() })
.ToArray());
ViewBag.Numbers = items;
And in my view I have the following:
@Html.DropDownListFor(m => m.Number, ViewBag.Numbers as IEnumerable<SelectListItem>, "Select a number")
@Html.ValidationMessageFor(m => m.Number)
It seems to work fine, if Javascript is enabled - when I select the first item (which is empty "Select a number"), Required validator kicks in and does not allow POSTing.
But when I disable Javascript, then I get an exception in my view right on that DropDownListFor method call:
The ViewData item that has the key 'Number' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.
When I comment out the [Range], then there is no such exception, but then it seems Required does not work - I can POST the empty "Select a number" option (which has value="") and my model passes validation, but it should not - empty string is not a valid integer! Why does it work fine with Javascript enabled, but fails server-side?
In your POST action don't forget to repopulate the ViewBag.Numbers
property, the same way you did in your GET action before returning the View:
[HttpPost]
public ActionResult SomeAction(MyViewModel model)
{
// some processing ...
// now repopulate the ViewBag if you intend to return the same view
ViewBag.Numbers = numbers
.Select(n => new SelectListItem {
Text = n.Number.ToString(),
Value = n.Number.ToString()
})
.ToList();
return View(model);
}