-1

当表格最初显示时,我会显示问题及其答案。我显示多个单选按钮来回答。所以用户只能选择一个答案。当我提交表单和操作方法调用时会出现问题。我看到当表单发布时,答案模型变得 null。因此,请指导我如何编写代码,结果答案模型在表单发布时不应为空。

这是完整的代码。请仔细阅读代码,如果需要更改,则当表单发布到操作方法时,答案模型不会为空。

我的 ViewModels 代码

namespace ViewModels
{
    public class Question
    {
        public int ID { set; get; }
        public string QuestionText { set; get; }

        public List<Answer> Answers { set; get; }
        [Required]
        public string 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>();
        }
    }
}

controller code

 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);           
        }

 [HttpPost]
        public ActionResult Index(Evaluation model)
        {
            if (ModelState.IsValid)
            {
                foreach (var q in model.Questions)
                {
                    if(q.Answers==null)
                    {
                        // Answers is null
                    }
                    var qId = q.ID;
                    var selectedAnswer = q.SelectedAnswer;
                    // Save the data 

                }
                return RedirectToAction("ThankYou"); //PRG Pattern
            }
            //reload questions
            return View(model);
        }

index.cshtml code

@model ViewModels.Evaluation
<h2>Quiz 24</h2>
@using (Html.BeginForm())
{
    @Html.EditorFor(x=>x.Questions)
    <input type="submit" />
}

and view code which is stored in EditorTemplates folder

@model ViewModels.Question
<div>
    @Html.HiddenFor(x=>x.ID)
    <h3> @Model.QuestionText </h3>

    @foreach (var a in Model.Answers)
    {
        <p>
            @Html.RadioButtonFor(b=>b.SelectedAnswer,a.ID)  @a.AnswerText 
        </p>

    }
</div>

问题就在这里

 [HttpPost]
        public ActionResult Index(Evaluation model)
        {
            if (ModelState.IsValid)
            {
                foreach (var q in model.Questions)
                {
                    if(q.Answers==null)
                    {
                        // Answers is null
                    }
                    var qId = q.ID;
                    var selectedAnswer = q.SelectedAnswer;
                    // Save the data 

                }
                return RedirectToAction("ThankYou"); //PRG Pattern
            }
            //reload questions
            return View(model);
        }

当我发布表单时,q.Answers==null 正在变为空。我想知道如何以这种方式编写代码的技巧,当表单将被发布到操作时,答案应该为空。许多人告诉我,我需要手动重建模型,因为 Answers 将始终为空。MVC 中是否没有任何机制可以保留所有数据并在发布表单时正确反序列化它以建模。

4

1 回答 1

0

AnswerText 通常我会建议Editor TemplateAnswer模型使用另一个嵌套,但在这种情况下,它会导致无法正确构造单选按钮组并随后检索SelectedAnswer. 作为一个简单的解决方案,我将通过以下方式调整Editor Templatefor模型:Question

<div>
    @Html.HiddenFor(x=>x.ID)
    <h3> @Model.QuestionText </h3>
    <div>
        @for (int i = 0; i < Model.Answers.Count; i++)
        {
            <p>
                @Html.RadioButtonFor(model => model.SelectedAnswer, Model.Answers[i].AnswerText  @Model.Answers[i].AnswerText
                @Html.HiddenFor(model => model.Answers[i].ID)
                @Html.HiddenFor(model => model.Answers[i].AnswerText)
            </p>
        }
    </div>
</div>

这将创建以下 HTML(跳过的不相关属性):

<input type="radio" name="Questions[0].SelectedAnswer" ...>
<input type="hidden" name="Questions[0].Answers[0].ID" ...>
<input type="hidden" name="Questions[0].Answers[0].AnswerText" ...>

输出将允许 MVC 正确地重建Answer集合。

更新

在您寻找的原始代码中Answer.AnswerText,所以我更新了代码以包含它而不是Answer.ID.

希望这可以帮助。

于 2013-09-22T10:15:43.427 回答