title: MVC 5 - JSON post to controller always is null on controller side
body: <p>I've looked for a couple hours now, hoping not to duplicate a question, and I just can't find what I'm looking for.</p>
  
  <p>I am working on passing a complex object back from a form to a controller, and having it parse everything out. The problem I get is the controller shows a null input, despite the header post from Chrome showing the data going out. Can anyone give me a hand? I've included code below.</p>
  
  <p><strong>Model</strong></p>
  
  <pre><code>public class QuizTakenObject
      {
          [NotMapped]
          public QuizTakenComplete quizTakenComplete { get; set; }
  
          [NotMapped]
          public List&lt;QuizSubmittedAnswers&gt; submittedAnswers { get; set; }
  
          [NotMapped]
          public TopicList Topic { get; set; }
  
          [NotMapped]
          public QuizHeader QuizHeader { get; set; }
  
      }
  </code></pre>
  
  <p><strong>View/Script</strong></p>
  
  <pre><code>@model App.Models.QuizTakenObject
  
  @{
      ViewBag.Title = "Take Quiz";
  }
  
  @section pageScripts{
      &lt;script type="text/javascript"&gt;
          $(document).ready(function () {
  
              //Highlight background of selected background for increased visibility
              $("input[name^=QuizSubmittedAnswer]").change(function () {
                  $(this).parent().addClass("bg-primary");
                  $(this).parent().siblings().removeClass("bg-primary");
              });
  
              //Show save prompt on page after one answer is picked
              var i = 0;
              if (i == 0) {
                  $("input[name^=QuizSubmittedAnswer]").change(function () {
  
                      $("#quizSave").fadeIn('fast');
                      $("#quizSave").animate({ height: '125px' }, 'fast')
                                    .animate({ width: '250px' }, 'fast', function () {
                                    $("#quizSaveText").fadeIn('500');
                          });
  
                  });
  
              }
  
              //Prevent submitting before all answers have been selected
              //Count all questions, one per form group
              var questionsCount = $("form-group").length;
  
              //Listen for answers to be selected
              $("input[name^=QuizSubmittedAnswer]").change(function () {
                  //Check to see if all answers are selected
                  if ($("input[name^=QuizSubmittedAnswer]:checked").length &gt;= questionsCount) {
                      $("#saveAndSubmitQuizButton").removeClass("disabled");
                  }
  
              });
  
              //Save and submit quiz
              $("#saveAndSubmitQuizButton").click(function () {
                  event.preventDefault;
  
                  var complete = true;
  
                  saveQuizAttempt(complete);
              });
  
              //Save but not submit quiz
              $("#saveQuizOnlyButton").click(function () {
                  event.preventDefault;
  
                  var complete = false;
  
                  saveQuizAttempt(complete);
              });
  
              //Create or update quiz attempt in DB
              //saveQuizAttempt complete indicates if the record is to be marked as final
              function saveQuizAttempt(complete) {
  
                  var array = $("#takeQuizForm").serializeArray();
  
                  //build JSON array
                  var json = {};
  
                  $.each(array, function () {
                      json[this.name] = this.value || '';
                  })
                  //array.push({ "IsComplete": complete });
  
  
                  //AJAX to post data
                  $.ajax({
                      type: "POST",
                      url: "SubmitQuiz",
                      data: JSON.stringify(array),
                      dataType: "json",
                      contentType:"application/json; charset=UTF-8",
  
                      success: function (data) {
                          console.log("Success!");
                      },
  
                      error: function () {
                          console.log("Error");
                      }
                  });
              }
  
  
          });
      &lt;/script&gt;
  }
  
  &lt;style&gt;
      #quizSave {
          display: none;
          position: fixed;
          z-index: 999;
          height: 0;
          width: 0;
          bottom: 100px;
          right: 0;
          background-color: khaki;
          border: 1px solid black;
          border-radius: 2px 2px 2px 2px;
          padding: .5em 1em .5em 1em;
      }
  &lt;/style&gt;
  
  &lt;h2&gt;@ViewBag.TopicName Quiz&lt;/h2&gt;
  
  &lt;div class="row"&gt;
      &lt;div class="container col-xs-9 col-sm-9 col-md-9 col-lg-9"&gt;
          &lt;div class="well well-sm"&gt;
              &lt;strong&gt;Directions:&lt;/strong&gt; @Model.QuizHeader.QuizSummary
          &lt;/div&gt;
  
          @using (Html.BeginForm("SubmitQuiz", "Quiz", FormMethod.Post, new { id = "takeQuizForm" }))
          {
              @Html.AntiForgeryToken()
  
              @Html.ValidationSummary(true, "", new { @class = "text-danger" })
              @Html.HiddenFor(model =&gt; model.QuizHeader.QuizID)
              @Html.HiddenFor(model =&gt; model.QuizHeader.TopicID);
              &lt;input type="hidden" name="QuizTakenComplete.UserID" id="QuizTakenComplete.UserID" value="@(ViewBag.UserID)" /&gt;
              &lt;input type="hidden" name="QuizTakenComplete.IsComplete" id="QuizTakenComplete.IsComplete" value="false" /&gt;
  
              &lt;!--Questions/Answers--&gt;
  
              for (int i = 0; i &lt; @Model.QuizHeader.QuizQuestions.Count(); i++)
              {
                  &lt;div class="quizQuestionBlock@(i)"&gt;
                      &lt;hr /&gt;
                      &lt;h4&gt;@Model.QuizHeader.QuizQuestions.ElementAt(i).Question&lt;/h4&gt;
                      &lt;form-group&gt;
                          &lt;input type="hidden" name="QuizSubmittedAnswers[@(i)].QuestionID" id="QuizSubmittedAnswers[@(i)].QuestionID" value="@(Model.QuizHeader.QuizQuestions.ElementAt(i).QuestionID)"&gt;
                          @{for (int j = 0; j &lt; Model.QuizHeader.QuizQuestions.ElementAt(i).QuizAnswers.Count(); j++)
                          {
  
                          &lt;!--answers via radio buttons--&gt;
                              &lt;div id="answer@(j)@(i)" class="quizAnswer@(j)"&gt;
                                  &lt;input type="radio" class="individualQuizAnswer" name="QuizSubmittedAnswers[@(i)].AnswerID" value="@Model.QuizHeader.QuizQuestions.ElementAt(i).QuizAnswers.ElementAt(j).AnswerID"&gt; @Model.QuizHeader.QuizQuestions.ElementAt(i).QuizAnswers.ElementAt(j).Answer
                              &lt;/div&gt;
  
                          }
  
                          }
                      &lt;/form-group&gt;
                  &lt;/div&gt;
              }
              &lt;hr /&gt;
              &lt;button class="btn btn-success btn-block disabled" id="saveAndSubmitQuizButton" type="button"&gt;submit quiz&lt;/button&gt;
              &lt;div style="text-align:center;"&gt;
                  &lt;small&gt; Submitting quiz will finalize this attempt and update your score records.&lt;/small&gt;
              &lt;/div&gt;
              &lt;br /&gt;
              &lt;br /&gt;
  
          }
  
      &lt;/div&gt;
  
  
      &lt;!--Sidebar--&gt;
      &lt;div class="container col-xs-3 col-sm-3 col-md-3 col-lg-3"&gt;
          &lt;div class="panel panel-default"&gt;
              &lt;div class="panel-heading collapsable"&gt;
                  &lt;h5&gt;&lt;span class="glyphicon glyphicon-cog"&gt;&lt;/span&gt; Actions&lt;/h5&gt;
              &lt;/div&gt;
              &lt;div class="panel-body"&gt;
                  &lt;span class="glyphicon glyphicon-backward"&gt;&lt;/span&gt; @Html.ActionLink("return to library", "Index", new { controller = "Library" })&lt;br /&gt;
                  @Html.ActionLink("cancel/go home", "Index", new { controller = "Home" }, new { @style = "color:red;" })
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;!--Quiz Save/Quit--&gt;
      &lt;div id="quizSave"&gt;
          &lt;div id="quizSaveText" style="display:none;"&gt;
              Save current answers and return to App training/quiz library?&lt;br /&gt;
              &lt;button type="button" id="saveQuizOnlyButton" class="btn btn-success"&gt;yes&lt;/button&gt;
              &lt;button type="button" data-toggle="tooltip" class="btn btn-danger" title="this will cancel all previous work without saving and return to the main menu"&gt;no&lt;/button&gt;
              &lt;br /&gt;
              &lt;small&gt;You will be able to return later to resume your work.&lt;/small&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p><strong>Controller</strong></p>
  
  <pre><code>//POST: Quiz/SubmitQuiz
  [HttpPost]
  public async Task&lt;ActionResult&gt; SubmitQuiz(string quizObject)
  {
      //Send false value for complete in AJAX call, just parse based on this
      //Two starting JS scripts, which flow into a unified function
  
      var input = new JavaScriptSerializer().Deserialize&lt;QuizTakenObject&gt;(quizObject);
  
      var quizTakenComplete = new QuizTakenComplete
      {
          UserID = input.quizTakenComplete.UserID,
          IsComplete = input.quizTakenComplete.IsComplete,
          LastUpdate = DateTime.Now
      };
  
      //Parse if complete for purposes of updating records.
      if (quizTakenComplete.UserID != null || quizTakenComplete.UserID != "")
      {
          db.QuizTakenComplete.Add(quizTakenComplete);
          await db.SaveChangesAsync();
  
          var quizAttemptID = quizTakenComplete.QuizAttemptID;
  
          //Now Add Each Answer
  
          var quizTaken = new QuizSubmittedAnswers();
          quizTaken.QuizAttemptID = quizAttemptID;
          quizTaken.TopicID = input.Topic.TopicID;
          quizTaken.QuizID = input.QuizHeader.QuizID;
  
  
  
          return Content("Saved");
      }
  
      else
      {
          return Content("Not Saved");
      }
  
   }
  </code></pre>