使控制器从继承视图模型中寻找属性 - 测试制作引擎

时间:2012-02-22 12:42:51

标签: asp.net-mvc asp.net-mvc-3 razor

在我的项目中,我必须编写测试引擎,它将从文件中读取测试任务,并进行查看,人们将回答:

  1. 一项测试有很多任务(任务列表)。
  2. 有4种类型的任务:radiobutton,checkbox,combobox,oneanswer。
  3. 在视图中,将列出测试中的所有任务。
  4. 我写过从文件中读取并创建视图的部分,但是我在控制器中接收答案时遇到问题 - 控制器只查找基本的viewModel属性。

    我这样做了:

    Model.cs

    public enum TaskTypeEnum
    {
        RadioButton, CheckBox, ComboBox, OneAnswer
    }
    public abstract class TaskModel
    {
        public abstract TaskTypeEnum TaskType { get; }
    
        public string Question { get; set; }
    
        public int TaskId { get; private set; }
    }
    
    public class RadioButtonTaskModel : TaskModel
    {
        public override TaskTypeEnum TaskType { get { return TaskTypeEnum.RadioButton; } }
    
        public List<string> Answers { get; set; }
    
        public string SelectedAnswer { get; set; }
    }
    // Other tasks have different properties than RadioButtonTaskModel
    

    ModelController.cs

        public ActionResult SolveTest()
        {
            List<TaskModel> taskList = GetTasksFromFile();
            return View(list);
        }
    
        [HttpPost]
        public ActionResult SolveTest(List<TaskModel> taskList)
        {
            // do something with task list
        }
    

    SolveTest.cshtml

    @model List<TaskModel>
    
    <h2>SolveTest</h2>
    
    <div>
    @using (Html.BeginForm())
    {
        foreach (var task in Model)
        {
            <div>
                <div>@task.Question</div>
                @if (task.TaskType == TaskTypeEnum.RadioButton)
                {
                    Html.RenderPartial("RadioButtonTaskView", task);
                }
            </div>
        }
        <p>
           <input type="submit" value="Solve" />
        </p>
    }
    </div>
    

    RadioButtonTaskView.cshtml

    @using  MvcApplication2.Models;
    @model RadioButtonTask
    
    <div>
        <ul>
        @foreach (var answer in Model.Answers)
        {
            <li>
                @Html.RadioButtonFor(
                    m => m.SelectedAnswer,
                    answer,
                    new { name = String.Format("taskList[{0}].SelectedAnswer", Model.TaskId) }
                    // it's for making sure, that controller will see that answer as part of list
                    // works fine, when main model is List<RadioButtonTaskModel>
                 );
                @answer
            </li>
        }
        </ul>
    </div>
    

    我当然削减了一些代码,但我认为这足以了解情况。

    问题是,HttpPost SolveTest中的Controller只查找base Task中包含的属性。如何让他从继承类中寻找属性?

    或许我完全错了,并且有一种更简单的方法来制作虚拟机列表?

1 个答案:

答案 0 :(得分:0)

您的设计存在一些固有缺陷:

  1. 如果您每页显示多个问题,并且存在多个相同类型的问题,则会将您的答案混合在一起,因为每个类型的名称都相同(例如,SelectedAnswer)。您需要一种方法来唯一地命名每个输入字段。
  2. 你的表单是动态的,但是你的SolveTest方法需要一个静态数量的参数,即使这样,它也永远不会工作,因为没有字段(至少从你向我们展示的那个)称为“taskList”。方法上的参数名称必须与HTML中输入字段的名称匹配(即。和int SelectedAnswer1)。因此,您需要一种方法将输入字段动态地连接到任务列表中的对象。为此,您必须查看FormCollection和/或Request []来执行此操作。