Reputation: 6122
Given this model code
[Required]
[Display(Name = "Name")]
public string Name { get; set; }
the following view code works
@Html.LabelFor(model => model.Name)
@Html.TextBoxFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
Whenever I leave the Name
field empty, the TextBox
is highlighted in red, and a "The Name field is required."
error message appears, which is good.
However, my model also contains an Option[] Options
which also need to be validated.
Given this model code
private const string orderNoDisplayName = "Order number";
[Required]
[RegularExpression(@"\d+",
ErrorMessage = "The " + orderNoDisplayName + " field must be numeric.")]
[Display(Name = orderNoDisplayName )]
public string OrderNo { get; set; }
the following view code doesn't quite work as expected
@foreach (var option in Option.GetDefaultOptions())
{
<li>
@Html.TextBoxFor(model => option.OrderNo, new { id = option.IdString })
@Html.ValidationMessageFor(model => option.OrderNo,
null, new { data_valmsg_for = option.IdString })
</li>
}
The very first option
works perfectly, but any subsequent option
doesn't.
Below is the automatically generated code for 2 option
s
<ul>
<li> <!-- automatically generated code for 'option_1' -->
<input data-val="true" data-val-regex="The Order number field must be numeric."
data-val-regex-pattern="\d+" data-val-required="The Order number field is required."
id="option_1" name="OrderNo" type="text" value="0" class="input-validation-error">
<span class="field-validation-valid" data-valmsg-for="option_1"
data-valmsg-replace="true"></span>
</li>
<li> <!-- automatically generated code for 'option_2' -->
<input id="option_2" name="OrderNo" type="text" value="0"
class="input-validation-error">
<span class="field-validation-valid" data-valmsg-for="option_2"
data-valmsg-replace="true"></span>
</li>
</ul>
So obviously, MVC did not add any validation attributes to my second option
or any subsequent option
s at all.
Of course, I could hardcode the validations into a handwritten <input>
tag, but I'd like to avoid doing so. What can I do to make the validation work for all option
s, instead of only the first one?
Upvotes: 2
Views: 2186
Reputation: 33306
I think the problem is the for loop, as the model binder is not indexing the name field they're coming out identical and it looks like there is only one i.e. name="OrderNo"
.
Try changing your loop to index it as follows:
@for (var i = 0; i < Option.GetDefaultOptions().Count; i++)
{
<li>
@Html.TextBoxFor(model => Option.GetDefaultOptions()[i].OrderNo, new { id = Option.GetDefaultOptions()[i].IdString })
@Html.ValidationMessageFor(model => Option.GetDefaultOptions()[i].OrderNo,
null, new { data_valmsg_for = Option.GetDefaultOptions()[i].OrderNo.IdString })
</li>
}
You should then see that they're written out as follows:
name="[0].OrderNo"
name="[1].OrderNo"
Upvotes: 4