Adam Mykel York Adam Mykel York - 20 days ago 6
ASP.NET (C#) Question

Checkbox and Radio button problems with asp.net core

I am trying to develop an online examination tool for my work. I have a class that defines an exam that contains a list of Questions, a class for Question that contains a list of Answers, and a class for Answer. I have a view model that pulls out the list of questions and passes it to the view as well as an array of ints to hold the value of the answer for each question. In the view, I loop through the questions, and in each question I loop through each possible answer. For multiple choice, this is easy. I just use:

<input asp-for="SelectedAnswer[q]" type="radio" value="@a" />@Model.Questions[q].answers[a].AnswerText


This works great, it passes the SelectedAnswer int array back the the controller on submit and I can do whatever I want with it. My problem comes down to if the question requires a checkboxlist for multiple right answers. I obviously cant use the same int array to post back the answer, so I hought about creating a second bool array for each of the checkboxes in a question and send that back. But this only really works for one question as each new question overrides the bool array on postback.

What I am trying to figure out is how to do this where I have different types of questions that can be displayed on a single page, and sent back to a controller when the submit button is pressed for processing.

Maybe I need a better view model? I am not sure where to go next with this.
I can provide any of the code required, I just didnt want to fill up the entire page with code.

My view:

@model DSCA_Exams.Models.ExamViewModels.ExamViewModel
<form asp-action="Exam_Results">
<div>
@for (int q = 0; q < Model.Questions.Count(); q++)
{
<div>
<hr />
<h4>@Model.Questions[q].QuestionText</h4>
<ul>
@for (int a = 0; a < Model.Questions[q].answers.Count(); a++)
{
<li>
@if (Model.Questions[q].QuestionType == 0)
{
<input asp-for="SelectedAnswer[q]" type="radio" value="@a" />@Model.Questions[q].answers[a].AnswerText
}
else
{
<input asp-for="@Model.isSelected[a]" />@Model.Questions[q].answers[a].AnswerText
}
</li>
}
</ul>
</div>
}
<hr />
<input type="submit" value="Grade Test" class="btn btn-default" />
</div>
</form>

Answer

Use view models and preserve the object graph. For example:

public class QuestionViewModel
{
    public string QuestionText { get; set; }
    public List<AnswerViewModel> Answers { get; set; }
    public List<int> SelectedAnswers { get; set; }
    ...
}

Then, in your view:

@for (var i = 0; i < Model.Questions.Count; i++)
{
    <p>@Model.Questions[i].QuestionText</p>

    @for (var j = 0; j < Model.Questions[i].Answers.Count; j++)
    {
        <label>
            <input asp-for="Questions[i].SelectedAnswers" type="radio" value="@Model.Questions[i].Answers[j].Id" />
            @Model.Questions[i].Answers[j].AnswerText
        </label>
    }
}

Then, when you post, the modelbinder will be able to preserve the object graph and you can inspect the SelectAnswers property of each question.