动态MVC RadioButton组选择的答案

时间:2014-09-13 03:56:01

标签: c# asp.net-mvc razor asp.net-mvc-5

我有一个动态填充的问题和答案列表。

两个问题:

  1. 回发后不显示问题和答案
  2. 缺少所选答案
  3. 视图模型

    public class RegistrationViewModel : RegisterExternalLoginModel
    {
        //...etc...
        public Question Question { get; set; }
        public Answer Answer { get; set; }
        public List<Question> Questions { get; set; }
        public IList<Answer> PossibleAnswers { get; set; }
        public List<SelectedAnswer> SelectedAnswers { get; set; }
        public IList<SelectedAnswer> PreviousAnswers 
        { 
            set 
            { 
                foreach(Question q in Questions)
                {
                    q.SelectedAnswers = value.Where(t => t.questionId == q.objectId).ToList() ;
                }
            } 
        }
    }
    

    选择的答案

     public Answer SelectedAnswer 
        { 
            get 
            {
                if (SelectedAnswers != null && SelectedAnswers.Count > 0)
                {
                    var answers = SelectedAnswers.Where(t => t.questionId == objectId);
                    if (answers.Count() == 1) 
                    {
                        var result = Answers.Where(t => t.objectId == answers.First().answerId).First();
                        return result;
                    }
                }
                return null;
            } 
        }
    

    的ActionResult

     public ActionResult CreateQuestions()
        {
            RegistrationViewModel vm = new RegistrationViewModel();
            IQFacade facade = new QFacade(CreateUserContext(true));
    
            //Questions and Answers
            vm.Questions = facade.GetQuestions().ToList();
            vm.PossibleAnswers = facade.GetPossibleAnswers();
    
            return View(vm);
    
        }
    

    发表

     [HttpPost]
     public ActionResult CreateQuestions(RegistrationViewModel vm)
        {
            var context = CreateUserContext(true);
    
                try{
                    IQFacade f = new QFacade(context);
                    f.CreateSomething(vm.User.name, vm.etc, vm.SelectedAnswers);//Need all the answers here, but null
                }
                catch (Exception ex)
                {
                    //error stuff, etc...
                    return View(vm);//the questions do not appear after this point. Do I need to bind them again from GetQuestions or shouldn't they still be a part of the vm object that I am returning?
                }
            }
    
            return RedirectToAction("Index");
        }
    

    在视图中,我使用的是编辑模板

     @Html.EditorFor(x => x.Questions)
    

    模板

      @foreach (var possibleAnswer in Model.Answers)
    {
        <div class="radio">
            @Html.RadioButtonFor(question => question.SelectedAnswer, possibleAnswer.objectId, new { id = possibleAnswer.objectId })
    
            <label for="@possibleAnswer.objectId">@possibleAnswer.text <span>@possibleAnswer.value</span></label> <p>@possibleAnswer.description</p>
        </div>
    }
    

    一切都是第一次有效,但不是在回发之后。我已经阅读了几十篇类似的SO帖子。我错过了什么?

1 个答案:

答案 0 :(得分:1)

基于评论,你的模型应该是这样的(不确定你所有的模型属性,所以我在这里做了一些假设)

public class QuestionVM
{
  public int ID { get; set; } // for binding
  public string Text { get; set; }
  [Required]
  public int? SelectedAnswer { get; set; } // for binding
  public IEnumerable<Answer> PossibleAnswers { get; set; }
}

public class RegistrationViewModel : RegisterExternalLoginModel
{
  public RegistrationViewModel()
  {
    Questions = new List<QuestionVM>();
  }
  //...etc...
  public List<QuestionVM> Questions { get; set; }
}

GET方法

public ActionResult CreateQuestions()
{
    RegistrationViewModel vm = new RegistrationViewModel();
    .....
    // Populate the questions and answers
    var questions = facade.GetQuestions().ToList();
    var answers = facade.GetPossibleAnswers();
    foreach (var question in questions)
    {
      QuestionVM qvm = new QuestionVM();
      qvm.ID = question.ID;
      qvm.Test = question.Text;
      // Add possible answers for the question
      qvm.PossibleAnswers = answers.Where(a => a.QuestionID ==  question.ID);
      // If loading existing questions/answers for existing user, also set value of current SelectedAnswer so its selected by default in the view
      vm.Questions.Add(qvm);
    }
    return View(vm);
}

查看

@model YourAssembly.RegistrationViewModel
....

@for(int i = 0; i < Model.Questions.Count; i++)
{
  @Html.HiddenFor(m > m.Questions[i].ID) // for binding
  @Html.DisplayFor(m > m.Questions[i].Text)
  foreach(var answer in Model.Questions[i].PossibleAnswers)
  {
    @Html.RadioButtonFor(m => m.Questions[i].SelectedAnswer, answer.ID, new { id = answer.ID})
    <label for="@answer.ID">answer.Text</label>
  }
}

POST方法

[HttpPost]
public ActionResult CreateQuestions(RegistrationViewModel vm)
{
  if (!ModelState.IsValid)
  {
    // You need to rebuild the question text and possible answers because these are not posted back
    return View(vm);
  }
  // Your model is now populated with the ID of each question and the selected answer which can be saved to the database

请注意,您可以为问题和答案文本值添加隐藏的输入,以便他们回发,但通常在控制器中重新加载的性能会更好(如果您包含正确的数据注释并包括客户端验证,则模型应始终为无论如何都有效回传)