Reputation: 119
OK, this is driving me nuts. I've got an MVC 4 website that is validating textboxes on the client, but not the dropdowns.
My (cut-down) model looks like this:
[Required]
public int? FabricOptionSelected { get; set; }
public List<SelectListItem> FabricOptions { get; private set; }
My (cut-down) controller looks like this:
model.FabricOptions.AddRange(product.Options
.Where(a=>a.ProductOptionCategory == Domain.Products.ProductOptionCategory.Fabric)
.ToSelectList( m => m.Name, m => m.Id.ToString(), "-- Select --"));
My (cut-down) view looks like this:
@if (Model.FabricOptions.Count > 1)
{
<div class="row form-group">
<div class="col-xs-2 control-label">Fabric</div>
<div class="col-xs-4">@Html.DropDownListFor(m => m.FabricOptionSelected, Model.FabricOptions, new { @class = "form-control" })</div>
<div class="col-xs-6">@Html.ValidationMessageFor(m => m.FabricOptionSelected)</div>
</div>
}
I have "~/Scripts/jquery.validate.js", and "~/Scripts/jquery.validate.unobtrusive.js" in my bundle config and the web.config has :
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
in the appsettings section.
Chrome console is not showing any errors and there is a text box with the Required attribute further down the page that is being fired.
.ToSelectList is an extension method:
public static List<SelectListItem> ToSelectList<T>
(this IEnumerable<T> enumerable,
Func<T, string> text,
Func<T, string> value,
string defaultOption)
{
var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList();
items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
return items;
}
Can't figure out why the client-side validation in the view isn't firing for the drop-downs. I figure I'm missing something obvious but could really do with a hand on this one.
Upvotes: 0
Views: 6297
Reputation:
Your extension method is inserting a "default" option which has a value="-1"
which is valid for an int
therefore there will be no error. You can achieve want you want using methods already available in MVC
Model
[Required]
public int? FabricOptionSelected { get; set; }
public SelectList FabricOptions { get; set; }
Controller
var option = product.Options.Where(a=>a.ProductOptionCategory == Domain.Products.ProductOptionCategory.Fabric);
model.FabricOptions = new SelectList(options, "ID", "Name");
View
@Html.DropDownListFor(m => m.FabricOptionSelected, Model.FabricOptions, "-- Select --", new { @class = "form-control" })
The 3rd parameter renders the first option of the <select>
as <option value>--Select--</option>
i.e. without a value so if that is selected, int? FabricOptionSelected
will be null
and therefore fail validation because of the [Required]
attribute
Upvotes: 1
Reputation: 11340
Make sure .ToSelectList
(is this an extension you added?) sets the default -- Select --
value to null
. Setting it to a nullable type is a good start but it needs to be null for Required to work.
Upvotes: 2