0

I'm using MVC, Have the following Model

public class Questionnaire 
     {
     public string Name { get; set; }
     public List<Question> Questions { get; set; }
 }

and Question class is :

public class Question 
 {
     public int QuestionNumber { get; set; }
     public string Body { get; set; }
     public IList<Option> Options { get; set; }
     //public IEnumerable<CreativeFactory.Option> OptionsTemp { get; set; }
     public Guid? QuestionnaireId { get; set; }
     public Guid? SelectedOption { get; set; }
     public int? SelectedEmployeeId { get; set; }

  } 

In my View I do foreach, and partially render a view

    % Html.BeginForm("Submit", "Questionnaire", FormMethod.Post); %>
    <%

    foreach (var q in Model.Questions)
    {
    Html.RenderPartial("Question", q);
    }
    %>
    <input type="submit" name="submit" value="submit" />
    <% Html.EndForm(); %>

My problem is the passed model to my action is always null

[AcceptVerbs(HttpVerbs.Post)]
         public ActionResult Submit(Questionnaire m)
         {
}

EDIT 1: Well, My Partial View Code is :

<%
 foreach (var option in Model.Options)
 {%>
   <p/>
 <%= Html.RadioButtonFor(x => x.SelectedOptionId, option.QuestionId, new { id = "test" +    option.ID })%>
<%
}     
%>

Even in the debugging Mode, I can't find my collection in the Form instance so even Custom Binding dosn't solve the problem, because the collection is not exist

any idea please?

1
  • Please check the element ID's rendered by your partial view. Are these in form that is supported by default model binder to list? Refer to Phil Haack's post related to "model binding to list" Commented Aug 22, 2011 at 12:26

3 Answers 3

3

I think you have to make Questionnaire implement ICollection<Question> and then follow these detailed instructions in Phil Haack's post. If you don't want Questionnaire to implement ICollection<Question>, I think you need to implement a custom model binder of the Questionnaire type.

Sign up to request clarification or add additional context in comments.

5 Comments

I Implemented ICollection, and checked the above link , But still have the same problem, Do you think the problem with Html.RenderPartial("Question", q); ?
Hard to tell unless you post code for RenderPartial. In general, if generated HTML conforms to the rules specified in that post, it should be okay.
The inputs in your partial view should have a name like "Questions[i].QuestionNumber" where i is the index (zero based) of the question. You should pass the index to the partial (or use QuestionNumber as index but be sure that it's zero for the first one) and check that you're generating the right names for the inputs so the model binder can do it's work.
Eduardo Campano, would you please clarify your solution based on the code above
@Aboelnil: Eduardo Campano is right, as well as Buu Nguyen answer. Please refer to this question and answer for further details on it.
1

This is the code for your partial, not tested. I assumed a zero based QuestionNumber:

<input type="hidden" name="Questions[<%= Model.QuestionNumber %>].QuestionNumber" value="<%= Model.QuestionNumber %>" />
<% foreach (var option in Model.Options) { %>
  <input type="radio" name="Questions[<%= Model.QuestionNumber %>].SelectedOptionId" value="<%= option.ID %>" /><%= option.Text %>
<% } %>

2 Comments

Eduardo, I just have one question please According to haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx , we don't use hidden fields, why we use it in your example
The key is to associate the question with the answer. I added it so in the Questionnaire that you receive in the action you get that property loaded, otherwise it will be zero or a default value. If you check that you will see that in the Questionary every Question will have null in the Body and also in the Options property, that is because the model binder didn't find information about those properties in the post values. If you remove the hidden you still will get the Questionnaire but you have to use the order of the questions to know to which question the answer corresponds.
0

Complete answer: MVC post a list of complex objects which contains Phil Haack's solution and another one too:

@for (var itemCnt = 0; itemCnt < Model.Questions.Count(); itemCnt++)
{
    @Html.TextBoxFor(m => Model.Questions[itemCnt].Body)
    ....
    @Html.HiddenFor(m => Model.Questions[itemCnt].QuestionNumber )
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.