I have a simple Question data model:
public class Question {
int QuestionId { get; set; }
string Text { get; set; }
string Answer { get; set; }
string ValidationMessage { get; set; }
};
Using this class I have built a view Model:
public class QuestionViewModel {
string Introduction { get; set; }
IEnumerable<Question> Questions { get; set; }
};
My Controller the builds the view model (from a data source) and renders the view:
@model QuestionViewModel
@using (Html.BeginForm()) {
if (Model.Questions != null) {
<ol>
@Html.EditorFor(m => Model.Questions)
</ol>
}
@Html.ValidationSummary("Unable to process answers...")
<input type="submit" value="submit" />
}
This view utilises an EditorTemplate:
@model Question
<li>
@Html.HiddenFor(m => m.Questionid)
@Html.TextBoxFor(m => m.Answer)
@Html.ValidationMessageFor(m => m.Answer)
</li>
For now, when the page is posted back, the controller validates the response:
[HttpPost]
public ActionResult Response(QuestionViewModel model) {
if (ModelState.IsValid) {
for (int i = 0; i < model.Questions.Count(); i++) {
Question q = model.Questions[i];
string questionId = String.Format("Questions[{0}]", i);
if (String.IsNullOrWhiteSpace(q.Answer)) {
ModelState.AddModelError(questionId, q.ValidationMessage);
}
}
}
}
The problem I'm having is that most of this works fine - the validates and the Validation Summary shows the correct validation messages. The problem is that I can't get individual field validators to render the error:
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="Questions[0].StringValue"></span>
As you can see, when I call the ModelState.AddModelError() method, I am currently using key value of the format "Questions[0]", but I have also tried "Questions_0" and various other combinations.
Any help/guidance would be much appreciated.
[Apologies for the overly long post]
I have found the answer - as with so many things, it was obvious once I broke the problem down - the ModelState.AddModelError() just needed a fully qualified key!
Modify the HttpPost Controller as follows:
[HttpPost]
public ActionResult Response(QuestionViewModel model) {
if (ModelState.IsValid) {
for (int i = 0; i < model.Questions.Count(); i++) {
Question q = model.Questions[i];
/*
** The key must specify a fully qualified element name including
** the name of the property value, e.g.
** "Questions[0].Answer"
*/
string questionId = String.Format("Questions[{0}].Answer", i);
if (String.IsNullOrWhiteSpace(q.Answer)) {
ModelState.AddModelError(questionId, q.ValidationMessage);
}
}
}
}