I am developing a page for rating questions.
In the view, I have a list of questions and 5 radio buttons in front of each one of them.
<input name="evalId" type="hidden" value="@Model.Evaluation.EvalId" />
foreach (var question in questionList)
{
<input name="questionId" type="hidden" value="@question.QuestionId" />
<div class="row_star" style="border-bottom : 0 none; background: none;">
@if (!String.IsNullOrEmpty(question.QuestionTitre))
{
<p>@question.QuestionTitre.TrimEnd()</p>
}
@* here goes the code for 5 radio buttons*@
}
Now, in my controller I want to be able to know which radio button was checked for each question.
How can I do that ?
Here is my ViewModel
public class EvaluationViewModel
{
/// <summary>
///
/// </summary>
public EvalEvaluation Evaluation
{
get;
set;
}
/// <summary>
///
/// </summary>
public Dictionary<EvalQuizz, List<EvalQuestion>> EvalQuizzQuestionList
{
get;
set;
}
}
Assuming your ViewModel is like this
public class Question
{
public int ID { set; get; }
public string QuestionText { set; get; }
public List<Answer> Answers { set; get; }
public int SelectedAnswer { set; get; }
public Question()
{
Answers = new List<Answer>();
}
}
public class Answer
{
public int ID { set; get; }
public string AnswerText { set; get; }
}
public class Evaluation
{
public List<Question> Questions { set; get; }
public Evaluation()
{
Questions = new List<Question>();
}
}
And in your GET action method, you will return the viewmodel back to the view with some questions and answers filled in it. In the code below I've hardcoded the questions and answers. You may get it from your Repositary/Service layer.
public ActionResult Index()
{
var evalVM = new Evaluation();
//the below is hardcoded for DEMO. you may get the data from some
//other place and set the questions and answers
var q1=new Question { ID=1, QuestionText="What is your favourite language"};
q1.Answers.Add(new Answer{ ID=12, AnswerText="PHP"});
q1.Answers.Add(new Answer{ ID=13, AnswerText="ASP.NET"});
q1.Answers.Add(new Answer { ID = 14, AnswerText = "Java" });
evalVM.Questions.Add(q1);
var q2=new Question { ID=2, QuestionText="What is your favourite DB"};
q2.Answers.Add(new Answer{ ID=16, AnswerText="SQL Server"});
q2.Answers.Add(new Answer{ ID=17, AnswerText="MySQL"});
q2.Answers.Add(new Answer { ID=18, AnswerText = "Oracle" });
evalVM.Questions.Add(q2);
return View(evalVM);
}
Now we will create an Editor Template to render our Question. so go to your View Folder and create a folder called EditorTemplates under the folder with your current controller name.
Add a view to the EditorTemplates folder and give the same name as the class name we want to represent. ie : Question.cshtml
Now put this code in the editor tempalte
@model YourNameSpace.Question
<div>
@Html.HiddenFor(x=>x.ID)
@Model.QuestionText
@foreach (var a in Model.Answers)
{
<p>
@Html.RadioButtonFor(b=>b.SelectedAnswer,a.ID) @a.AnswerText
</p>
}
</div>
Now go to our main view and use EditorTemplate html helper method to bring the EditorTemplate we created to the main view.
@model YourNameSpace.Evaluation
<h2>Index</h2>
@using (Html.BeginForm())
{
@Html.EditorFor(x=>x.Questions)
<input type="submit" />
}
Now in your HttpPost you can check the posted model and get the selected radio button (SelectedAnswer) value there
[HttpPost]
public ActionResult Index(Evaluation model)
{
if (ModelState.IsValid)
{
foreach (var q in model.Questions)
{
var qId = q.ID;
var selectedAnswer = q.SelectedAnswer;
//Save
}
return RedirectToAction("ThankYou"); //PRG Pattern
}
//reload questions
return View(model);
}
If you use visual studio breakpoints, you can see the values posted. Thanks to MVC Model binding :)
You can read about it and download a working sample here.