When I try and pass the data from the view to the controller, the parameters in debug mode show up as null when defined as a List (In the save method).
Here is the method in the controller that is getting the exception when trying to save data. When they were just objects (Category category instead of List< Category > category) they were returning the first instance of data, but weren't null).
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(Survey survey, List<Category> category, List<Question> question, List<Answer> answer)
{
if (survey.SurveyId == 0)
{
_context.Surveys.Add(survey);
foreach (var categorytoAdd in category)
_context.Categories.Add(categorytoAdd);
foreach (var questiontoAdd in question)
_context.Questions.Add(questiontoAdd);
foreach (var answertoAdd in answer)
_context.Answers.Add(answertoAdd);
}
else
{
foreach (var surveyInDb in _context.Surveys.Where(m => m.SurveyId == survey.SurveyId))
surveyInDb.Description = survey.Description;
//old code before switching to a list
//foreach (var categoryInDb in _context.Categories.Where(m => m.CategoryId == category.CategoryId))
//categoryInDb.CategoryDescription = category.CategoryDescription;
//foreach (var questionInDb in _context.Questions.Where(m => m.QuestionId == question.QuestionId))
// questionInDb.QuestionText = question.QuestionText;
//foreach (var answerInDb in _context.Answers.Where(m => m.AnswerId == answer.AnswerId))
// answerInDb.AnswerText = answer.AnswerText;
foreach (var categorytoAdd in category)
{
foreach (var categoryInDb in _context.Categories.Where(m => m.CategoryId == categorytoAdd.CategoryId))
categoryInDb.CategoryDescription = categorytoAdd.CategoryDescription;
}
foreach (var questiontoAdd in question)
{
foreach (var questionInDb in _context.Questions.Where(m => m.QuestionId == questiontoAdd.QuestionId))
questionInDb.QuestionText = questiontoAdd.QuestionText;
}
foreach (var answertoAdd in answer)
{
foreach (var answerInDb in _context.Answers.Where(a => a.AnswerId == answertoAdd.AnswerId))
answerInDb.AnswerText = answertoAdd.AnswerText;
}
}
_context.SaveChanges();
return RedirectToAction("Index", "Surveys");
}
And the view that the data is being sent from. I'm looping through all the categories, questions in the categories, and answers for the questions. I'm not even sure if I actually need the HiddenFields here.
@using (Html.BeginForm("Save", "Surveys"))
{
<div class="form-group">
@Html.LabelFor(s => s.SurveyId)
@Html.TextBoxFor(s => s.Description, new { @class = "form-control" })
@Html.ValidationMessageFor(s => s.Description)
</div>
<div id="Survey" class="form-group">
@foreach (var category in Model.Categories.Where(c => c.SurveyId == Model.SurveyId))
{
<ul>@Html.LabelFor(c => category.CategoryId)</ul>
<ul>@Html.TextBoxFor(c => category.CategoryDescription, new { @class = "form-control" })</ul>
@Html.HiddenFor(c => category.CategoryId)
@Html.HiddenFor(c => category.CategoryDescription)
foreach (var question in Model.Questions.Where(q => q.CategoryId == category.CategoryId))
{
<ul>@Html.LabelFor(q => question.QuestionId)</ul>
<ul>@Html.TextBoxFor(q => question.QuestionText, new { @class = "form-control" })</ul>
@Html.HiddenFor(q => question.QuestionId)
@Html.HiddenFor(q => question.QuestionText)
foreach (var answer in Model.Answers.Where(a => a.QuestionId == question.QuestionId))
{
<ul>@Html.LabelFor(a => answer.AnswerId)</ul>
<ul>@Html.TextBoxFor(a => answer.AnswerText, new { @class = "form-control" })</ul>
@Html.HiddenFor(a => answer.AnswerId)
@Html.HiddenFor(a => answer.AnswerText)
}
}
}
</div>
@Html.HiddenFor(m => m.SurveyId)
@Html.AntiForgeryToken()
<button type="submit" class="btn btn-primary">Save</button>
}
My guess is that somewhere in the view the data isn't being properly sent to the controller, otherwise it wouldn't be null. Does this problem originate from a bad send from the view to the controller?
The Class (view model) that is being used here is
public class NewSurveyViewModel
{
public List<Category> Categories { get; set; }
public List<Question> Questions { get; set; }
public List<Answer> Answers { get; set; }
[Display(Name = "Survey Name")]
public int? SurveyId { get; set; }
[Required(ErrorMessage = "The survey name cannot be blank")]
public string Description { get; set; }
public NewSurveyViewModel()
{
SurveyId = 0;
}
}
I apologize for the huge block of code, but I figured this would all be relevant and didn't want to leave anything out for a better picture.