为调查构建动态表单和控制器

时间:2015-07-20 16:13:58

标签: c# asp.net-mvc survey

我需要创建一个100%动态调查项目,用户可以在其中创建每个问题和每个答案的类型(多个/文本/广播)。

我的知识终结于Controller,因为我总是基于静态视图和静态模型构建它们,但这次我不知道将在表单中提交什么。

在视图中我认为最好的选择将包括基于表格内调查配置的PartialViews。

我发现数据库模型架构的第一步是:

What mysql database tables and relationships would support a Q&A survey with conditional questions?

但是我找不到任何开始构建代码的例子。

2 个答案:

答案 0 :(得分:1)

我有一些在服务器端视图和AngularJS中构建类似产品的经验。无论采用哪种方法,您的解决方案都将如下所示:

  • 为所有SurveyQuestions创建一个通用模型,定义一个Type参数,该参数可用于特定于类型的呈现逻辑
  • 为每种类型的调查问题创建部分视图,并使用必要的逻辑来呈现它
  • 创建一个"渲染器"部分视图,它接受SurveyQuestion对象,然后选择正确的子视图来呈现该组件
  • 在循环中调用RenderPartial("Renderer", SurveyQuestion)以呈现每种类型的问题
  • 使用控制器逻辑处理答案

就个人而言,我建议使用AngularJS(或类似的)这样的东西,因为它会简化将不同的问题粘合成一个序列;只要注意设置历史记录状态,以便用户可以前后导航,如果支持的话。

修改 - 这是数据模型和分组逻辑的基本示例:https://dotnetfiddle.net/4mhrxO

答案 1 :(得分:1)

对每个问题类型使用部分视图不会轻松工作,因为默认情况下,它们不会在表单控件前添加name属性和发布时绑定所需的集合索引器,并且您将需要多个条件语句来确定哪个部分显示。

假设可以接受根据类型对视图中的问题进行分组,然后对每种类型或EditorTemplate循环使用自定义for。基本模型结构可能是

public enum QuestionType
{
    YesNo,
    Text,
    MultipleChoice
}
public class Survey
{
    public int ID { get; set; }
    public string Title { get; set; }
    public List<YesNoQuestion> YesNoQuestions { get; set; }
    public List<TextQuestion> TextQuestions { get; set; }
    public List<MultipleChoiceQuestion> MultipleChoiceQuestions { get; set; }
}
public abstract class Question
{
    public int ID { get; set; }
    public string Text { get; set; }
    public QuestionType Type { get; set; }
}
public class YesNoQuestion : Question
{
    public bool Answer { get; set; }
}
public class TextQuestion : Question
{
    public string Answer { get; set; }
}
public class MultipleChoiceQuestion : Question
{
    public int Answer { get; set; }
    public List<MultipleChoiceAnswer> PossibleAnswers { get; set; }
}
public class MultipleChoiceAnswer
{
    public int ID { get; set; }
    public int QuestionID { get; set; }
    public string Text { get; set; }
}

和简化视图(使用for循环)

@model yourAssembly.Survey
@using (Html.BeginForm())
{
  <h2>@Html.DisplayFor(m => m.Title)</h2>
  <h3>Yes/No questions</h3>
  for(int i = 0; i < Model.YesNoQuestions.Count; i++)
  {
    <div>   
      @Html.CheckBoxFor(m => m.YesNoQuestions[i].Answer)
      @Html.LabelFor(m => m.YesNoQuestions[i].Answer, Model.YesNoQuestions[i].Text)
    </div>
  }
  <h3>Text questions</h3>
  for(int i = 0; i < Model.TextQuestions.Count; i++)
  {
    @Html.LabelFor(m => m.TextQuestions[i].Answer, Model.TextQuestions[i].Text)
    @Html.TextAreaFor(m => m.TextQuestions[i].Answer)
  }
  <h3>Multiple choice questions</h3>
  for(int i = 0; i < Model.MultipleChoiceQuestions.Count; i++)
  {
    <div>@Html.DisplayFor(m => m.MultipleChoiceQuestions[i].Text)</div>
    foreach(var option in Model.MultipleChoiceQuestions[i].PossibleAnswers)
    {
      var id = string.Format("option-{0}", option.ID);
      <div>
        @Html.RadioButtonFor(m => m.MultipleChoiceQuestions[i].Answer, option.ID, new { id = id })
        <label for="@id">@option.Text</label>
      </div>
    }
  }
  <input type="submit" value="Save" />
}