I'm trying to get a good grasp on ASP.Net MVC, Razor and RadioButtons, so I tried to make a quiz to test my skills.
I implemented a working quiz form in the following way in Razor (not posting the controller that manages it and just showing the important part of the view file):
@using (Html.BeginForm("Quiz", "CourseDetail", FormMethod.Post)) {
<div class="question-list">
@Html.HiddenFor(m => m.CurrentChapter.ChapterId)
@for (int i = 0; i < Model.CurrentChapter.Questions.Count; i++) {
@Html.HiddenFor(m => Model.CurrentChapter.Questions[i].Id)
<div class="question @(Model.CurrentChapter.Questions[i].Resolved ? "question-resolved" : "")">
<div class="question-number">@Model.CurrentChapter.Questions[i].Id</div>
<div class="question-title">@Html.Raw(Model.CurrentChapter.Questions[i].QuestionText)</div>
<ul class="question-answers">
@for (int j = 0; j < Model.CurrentChapter.Questions[i].QuestionAnswers.Count; j++) {
<li class="@(Model.CurrentChapter.Questions[i].Resolved && Model.CurrentChapter.Questions[i].QuestionAnswers[j].Correct ? "correct-answer" : "")">
<label>
<span class="@(Model.CurrentChapter.Questions[i].Resolved && Model.CurrentChapter.Questions[i].QuestionAnswers[j].Correct && Model.CurrentChapter.Questions[i].AnsweredCorrectly ? "checked" : "")">
@Html.RadioButtonFor(m => m.CurrentChapter.Questions[i].SelectedAnswer.Id, Model.CurrentChapter.Questions[i].QuestionAnswers[j].Id)
</span>
@Model.CurrentChapter.Questions[i].QuestionAnswers[j].AnswerText
</label>
</li>
}
</ul>
</div>
}
</div>
<div class="row text-right">
<div class="span3 offset9">
<button type="submit" class="btn btn-primary btn-large btn-block">Compruebe los resultados</button>
</div>
</div>
}
However, this is quite bloated to be put on a single file although it works (Maybe putting the the template for questions in a separate file). While trying to refactor, I found the following issues (which I would be grateful if someone could answer them too):
- Couldn't use foreach clauses because
@Html.RadioButtonFor
not@Html.HiddenFor
didn't work with inner loop variables. ASP.Net model binding couldn't post well the variables. - Couldn't use neither
Html.DisplayFor
norEditorFor
due to the previous posting problem.
So, how can I refactor this properly and separate in in several files while being able to post it properly? The underlying model is this one:
public class Course
{
public string Title { get; set; }
public string Description { get; set; }
public string Category { get; set; }
public string Image { get; set; }
public string Link { get; set; }
public PageReference PageRef { get; set; }
public List<Chapter> Chapters { get; set; }
public Course() {
Chapters = new List<Chapter>();
}
}
public class Chapter
{
public Guid ChapterId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Category { get; set; }
public string Image { get; set; }
public string Link { get; set; }
public List<Question> Questions { get; set; }
public Chapter() {
Questions = new List<Question>();
}
}
public class Question
{
public int Id { get; set; }
public string QuestionText { get; set; }
public List<Answer> QuestionAnswers { get; set; }
public Answer SelectedAnswer { get; set; }
public bool Resolved { get; set; }
public bool AnsweredCorrectly { get; set; }
public Question() {
QuestionAnswers = new List<Answer>();
}
}
public class Answer
{
public int Id { get; set; }
public string AnswerText { get; set; }
public bool Correct { get; set; }
public static Answer Parse(string answer, int id)
{
return new Answer
{
Id = id,
AnswerText = answer.Replace("*", ""),
Correct = answer.StartsWith("*"),
};
}
}
public class CourseContentViewModel : PageViewModel<CoursePage>
{
public CourseContentViewModel(CoursePage currentPage)
: base(currentPage)
{
}
public Course Course { get; set; }
public Chapter CurrentChapter { get; set; }
}
public class QuizViewModel : CourseContentViewModel
{
public QuizViewModel(CoursePage currentPage)
: base(currentPage)
{
}
public QuizViewModel() : base(null) {
}
public List<Question> Questions { get; set; }
public bool HasAnswered { get; set; }
public int NumberOfCorrectAnswers { get; set; }
}
EditorTemplates
? – danrhul Dec 3 '14 at 11:29