Search code examples
asp.net-mvcdictionaryasp.net-corerazorradio-button

C# MVC Radio Button Names and Values groups pass into [HTTPPost]


Hello All I'm new to this so bare with me. I have a very simple Survey build in C# MVC5 that i need to collect the results from the grouping radio buttons for 5 questions.

For each question has about 3-4 choices. I manage to present the question and choices into my cshtml. Now I'm wrapping in my head how to capture the data and save it into a dictionary or List to Pass it over the Controller. This is where I need a little help. In the Model I have a class ListAnswers just sitting there if needed which can hold the values from the radio, THe most important thing to capture is QuestionID and Choice Option either the text or the id of the choice.

Please use very Beginner coding here as I'm learning. Thank You.

@model PMLessonLearned.Models.ViewSurvey
@using (Html.BeginForm("Surveys", "Home"))
{
    @Html.AntiForgeryToken()
    foreach (var qu in Model.Questions)
    {
        <dt>
            @Html.DisplayFor(modelItem => qu.Question)
        </dt>
        foreach (var ch in Model.Choices)
        {
            if (qu.QID == ch.QuestionID)
            {
                <dd>
                    <div>
                        @Html.RadioButton("Q_" + ch.QuestionID, ch.ChoiceOption)
                        @Html.DisplayFor(modelItem => ch.ChoiceOption)
                    </div>
                </dd>
            }
        }
    }
    <dt>
        <input type="submit" class="btn btn-primary btn-sm" value="Submit" />
    </dt>
}

This is capture by group under name = Q_1 , Q_2, etc. (which use the ch.QuestionID) the ch.ChoiceOption is the actual wording: "Yes" , "No", "Not Sure" , etc.

Html Example:

<input id="Q_4" name="Q_4" type="radio" value="All the time">
<input id="Q_2" name="Q_2" type="radio" value="No">

This is my HomeController:

         [HttpGet]
        public ActionResult Surveys()
        {
            ViewSurvey m = new ViewSurvey();
            m.PopulateQuestions();
            m.PopulateChoices();
            return View(m);
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Surveys(ViewSurvey m)
        {
            var testrestuls = m;
            return RedirectToAction("Index", "Home");
        }

ShowSurvey.cs Model:

        public class ListQuestions
    {
        public int QID { get; set; }
        public string Question { get; set; }
    }
    public class ListChoices
    {
        public int CID { get; set; }
        public int QuestionID { get; set; }
        public string ChoiceOption { get; set; }
    }
    public class ListAnswers
    {
        public int AID { get; set; }
        public int AQuestionID { get; set; }
        public string AnswerText { get; set; }
        public int ChoiceID { get; set; }
    }
    public class ViewSurvey
    {
        public IEnumerable<ListQuestions> PopulateQuestions()
        {
            Entitydb db = new Entitydb();
            var m = (from e in db.SurveyQuestions
                     select new ListQuestions()
                     {
                         QID = e.ID,
                         Question = e.Question
                     }).ToList();
            return m;
        }
        public IEnumerable<ListChoices> PopulateChoices()
        {
            Entitydb db = new Entitydb();
            var m = (from e in db.SurveyQuestions
                     join c in db.SurveyQuestionChoices on e.ID equals c.QuestionID
                     select new ListChoices()
                     {
                         CID = c.ID,
                         QuestionID = c.QuestionID,
                         ChoiceOption = c.Choice,
                     }).ToList();
            return m;
        }
    }

This is how it's displayed: Survey Look


Solution

  • Asp.net core bind model with name attribute.You can change your name value of radiobutton.And add hidden input of QuestionId and choiceOption.

    Here is a demo,after each radiobutton,I add a hidden input with choiceoption,and before form submit,I change the name of hiddeninput after checked radiobutton to right format.

    View:

    @using (Html.BeginForm("Surveys", "Home"))
    {
        @Html.AntiForgeryToken()
        var i = 0;
        foreach (var qu in Model.Questions)
        {
            <input hidden name="Answers[@i].AQuestionID" [email protected]>
            <dt>
                @Html.DisplayFor(modelItem => qu.Question)
            </dt>
            foreach (var ch in Model.Choices)
            {
                if (qu.QID == ch.QuestionID)
                {
                    <dd>
                        <div>
                            @Html.RadioButton("Answers[" + i + "].ChoiceID", ch.CID)
                            @Html.TextBoxFor(modelItem => ch.ChoiceOption, new { @hidden = "hidden" })
                            @*@Html.EditorFor(modelItem => ch.ChoiceOption, new { @hidden = true })*@
                            @*<input [email protected] hidden />*@
                            @Html.DisplayFor(modelItem => ch.ChoiceOption)
                        </div>
                    </dd>
                }
            }
            i++;
        }
        <dt>
            <input type="submit" class="btn btn-primary btn-sm" value="Submit" />
        </dt>
    }
    <script>
            $("form").submit(function () {
                $("input[type='radio']").each(function () {
                    if ($(this).is(":checked")) {
                        $(this).next().attr("name", $(this).attr("name").split("ChoiceID")[0] + "AnswerText");
                    }
                })
            })
        </script>
    

    Models:

    public class ListQuestions
        {
            public int QID { get; set; }
            public string Question { get; set; }
        }
        public class ListChoices
        {
            public int CID { get; set; }
            public int QuestionID { get; set; }
            public string ChoiceOption { get; set; }
        }
        public class ListAnswers
        {
            public int AID { get; set; }
            public int AQuestionID { get; set; }
            public string AnswerText { get; set; }
            public int ChoiceID { get; set; }
        }
        public class ViewSurvey
        {
            public IEnumerable<ListQuestions> Questions { get; set; }
            public IEnumerable<ListChoices> Choices { get; set; }
        }
    

    Controller(I use fake data to test):

    [HttpGet]
            public ActionResult Surveys()
            {
                ViewSurvey v = new ViewSurvey
                {
                    Questions = new List<ListQuestions> {
                    new ListQuestions{ QID=1, Question="How often during the lifecycle of your project you use lesson learned?" },
                    new ListQuestions{ QID=2, Question="Do you know how to build a lesson learned template?" },
    
                 },
                    Choices = new List<ListChoices> {
                        new ListChoices{  CID=11,QuestionID=1, ChoiceOption="All the Time"},
                        new ListChoices{  CID=12,QuestionID=1, ChoiceOption="Sometimes"},
                        new ListChoices{  CID=13,QuestionID=1, ChoiceOption="Never"},
                        new ListChoices{  CID=14,QuestionID=1, ChoiceOption="Rarely"},
                        new ListChoices{  CID=21,QuestionID=2, ChoiceOption="No"},
                        new ListChoices{  CID=22,QuestionID=2, ChoiceOption="Yes"},
                        new ListChoices{  CID=23,QuestionID=2, ChoiceOption="Sometimes"},
    
    
    
                    }
                };
                return View(v);
            }
            [HttpPost]
            [ValidateAntiForgeryToken]
            public IActionResult Surveys(List<ListAnswers> Answers)
            {
                return Ok();
            }
    

    result: enter image description here