Ответ 1
В вашем коде есть ряд проблем, включая создание дубликата id
(недопустимый html), создание дубликатов атрибутов name
(поэтому вы создаете только одну группу, но, что более важно, это не даст вам привязки к модели, когда вы отправляете назад), и вы вообще не привязываетесь к действительному свойству.
Вам нужно будет создать модели представлений для представления того, что вы хотите отображать, а также редактировать и генерировать радиокнопки в цикле for
(или с помощью EditorTemplate
), чтобы они были правильно названы с индексаторами.
Просмотр моделей
public class QuestionVM
{
public int ID { get; set; } // for binding
public string Text { get; set; }
[Required]
public int? SelectedAnswer { get; set; } // for binding
public IEnumerable<AnswerVM> PossibleAnswers { get; set; }
}
public class SubjectVM
{
public int? ID { get; set; }
[DisplayFormat(NullDisplayText = "General")]
public string Name { get; set; }
public List<QuestionVM> Questions { get; set; }
}
public class AnswerVM
{
public int ID { get; set; }
public string Text { get; set; }
}
public class StudentVM
{
public int ID { get; set; }
public string Name { get; set; }
// plus any other properties of student that you want to display in the view
public List<SubjectVM> Subjects { get; set; }
}
Вид
@model YourAssembly.StudentVM
@using(Html.BeginForm())
{
@Html.HiddenFor(m => m.ID)
@Html.DisplayFor(m => m.Name)
for(int i = 0; i < Model.Subjects.Count; i++)
{
@Html.HiddenFor(m => m.Subjects[i].ID)
@Html.DisplayFor(m => m.Subjects[i].Name) // will display "General" if no name
for (int j = 0; j < Model.Subjects[i].Questions.Count; j++)
{
@Html.HiddenFor(m => m.Subjects[i].Questions[j].ID)
@Html.DisplayFor(m => m.Subjects[i].Questions[j].Text)
foreach(var answer in Model.Subjects[i].Questions[j].PossibleAnswers )
{
<div>
@Html.RadioButtonFor(m => m.Subjects[i].Questions[j].SelectedAnswer, answer.ID, new { id = answer.ID})
<label for="@answer.ID">@answer.Text</label>
</div>
}
@Html.ValidationMessageFor(m => m.Subjects[i].Questions[j].SelectedAnswer)
}
}
<input type="submit" value="save" />
}
контроллер
public ActionResult Edit(int ID)
{
StudentVM model = new StudentVM();
// populate your view model with values from the database
return View(model);
}
[HttpPost]
public ActionResult Edit(StudentVM model)
{
// save and redirect
}
Примечание. Я немного смущен структурой базы данных, подразумеваемой вашими моделями (например, почему вам нужны отдельные модели для Question
и SubjectQuestion
, когда значение null
для SubjectID
идентифицирует его как "Общее" вопрос). Я предлагаю вам начать с жесткого кодирования некоторых значений в методе GET, чтобы увидеть, как он работает и отправляет сообщения.
StudentVM model = new StudentVM();
model.ID = 1;
model.Name = "bambiinela";
model.Subjects = new List<SubjectVM>()
{
new SubjectVM()
{
Questions = new List<QuestionVM>()
{
new QuestionVM()
{
ID = 1,
Text = "Question 1",
SelectedAnswer = ?, // set this if you want to preselect an option
PossibleAnswers = new List<AnswerVM>()
{
new AnswerVM()
{
ID = 1,
Text = "Answer A"
},
new AnswerVM()
{
ID = 1,
Text = "Answer B"
}
}
},
new QuestionVM()
{
ID = 2,
Text = "Question 2",
PossibleAnswers = new List<AnswerVM>()
{
// similar to above
}
}
}
},
new SubjectVM()
{
ID = 1,
Name = "Math",
Questions = new List<QuestionVM>()
{
// similar to above
}
}
};
Когда вы отправляете сообщение, модель заполняется идентификатором выбранного ответа для каждого вопроса в каждом предмете. Обратите внимание на использование DisplayFor()
для некоторых свойств. Они не будут отправлять сообщения, поэтому вам нужно будет повторно заполнить эти свойства, если вы вернете представление (например, ModelState
недействительно). В качестве альтернативы вы можете создать текстовое поле только для чтения или добавить скрытый ввод для этих свойств. Я также предлагаю вам проверить созданный HTML-код, в частности атрибуты имени, которые будут выглядеть примерно как
<input type="radio" name="Subjects[0].Questions[0].SelectedAnswer" ...
чтобы дать вам представление о том, как коллекции привязаны к вашей модели при отправке назад.