2

I have a pretty simple pair of classes:

public class Question
{
    [Key]
    public int QuestionId { get; set; }
    [Required]
    [Display(Name ="Question Text")]
    public string QuestionText { get; set; }

    public virtual IList<Answer> Answers { get; set; }
}

public class Answer : IValidatableObject
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid AnswerId { get; set; }
    [Required]
    [Display(Name = "Answer Text")]
    public string AnswerText { get; set; }
    [Required]
    [Display(Name = "Is Correct")]
    public bool IsCorrect { get; set; }
}

And I'm trying to make an editor page the MVC way to edit both the question and the answers. So I have something like this:

@using (Html.BeginForm())
{
   <input type="submit" value="Save Question" class="btn btn-default" />

   @Html.HiddenFor(model => model.QuestionId)
   @Html.EditorFor(model => model.QuestionText, new { htmlAttributes = new { @class = "form-control" } })

   <h4>Answers:</h4>
   @Html.EditorFor(model => model.Answers)
}

And a template for the Answer something like this:

@Html.HiddenFor(model => model.AnswerId)
@Html.EditorFor(model => model.AnswerText, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.IsCorrect)

And loading the page everything looks good. I can see it's bound both the questions and the answers. But on submission, the Question object is populated, but Answers is null. But it looked like the submission did include all the fields I'd expect:

QuestionId:36
QuestionText:This is a test
Answers[0].AnswerId:0b5a2bdd-32fd-e711-93fc-b8ca3a683254
Answers[0].AnswerText:TRUE
Answers[0].IsCorrect:true
Answers[0].IsCorrect:false
Answers[1].AnswerId:0c5a2bdd-32fd-e711-93fc-b8ca3a683254
Answers[1].AnswerText:FALSE
Answers[1].IsCorrect:false

So what's going on here? From what I've read (a lot of it for previous versions of MVC) this should just work. Is it because of using a GUID as an id? What am I missing to make this bind properly?

Ultimately I'd like to be able to add and remove Answers, but one step at a time here.

EDIT: weirdly it is sending Answers[0].IsCorrect twice. Here's the generated HTML that it produced:

<input checked="checked" class="check-box" data-val="true" data-val-required="The Is Correct field is required." id="Answers_0__IsCorrect" name="Answers[0].IsCorrect" type="checkbox" value="true">
<input name="Answers[0].IsCorrect" type="hidden" value="false">

For the other answer (Answer[1]) it generates, which only results in one value for Answers[1].IsCorrect:

<input class="check-box" data-val="true" data-val-required="The Is Correct field is required." id="Answers_1__IsCorrect" name="Answers[1].IsCorrect" type="checkbox" value="true">
<input name="Answers[1].IsCorrect" type="hidden" value="false">
Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • `Answers[0].IsCorrect:true Answers[0].IsCorrect:false` is this the actual data or just a mistake copy-pasting? – Camilo Terevinto Jan 19 '18 at 17:22
  • @CamiloTerevinto: I had to double check, and oddly, it really is there. But only for `[0]` and not `[1]` – Matt Burland Jan 19 '18 at 17:41
  • I've never used EditorFor (I like being in control of the HTML), but check whether you have two ` – Camilo Terevinto Jan 19 '18 at 17:43
  • @CamiloTerevinto: It seems it produces a pair of `input` controls for each one. One is hidden and the other not. Maybe that's something to do with it, but I don't understand why it does it. – Matt Burland Jan 19 '18 at 18:26
  • 1
    The 2 inputs for are generated to ensure a value is posted back (if its checked, it posts `true` and `false` (the `DefaultModelBinder` only binds the first one) and if its unchecked, it posts back `false` (because unchecked checkboxes do not submit a value) –  Jan 19 '18 at 22:38
  • The code you have shown works fine (although you did not show you POST method - it should be something like `public ActionResult Edit (Question model)` –  Jan 19 '18 at 22:40
  • As a side note, will not be able to use `EditorFor()` to generate you collection if your wanting to dynamically add and remove items. Refer the answers [here](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) and [here](http://stackoverflow.com/questions/40539321/partial-view-passing-a-collection-using-the-html-begincollectionitem-helper/40541892#40541892) for some options you can use –  Jan 19 '18 at 22:41

0 Answers0