1

我在让我的控制器在回发时识别子类模型时遇到问题。

我正在使用存储在数据库中的字段元数据创建一个动态 Web 表单。对于我的 ViewModel,我有两种父类型

public class Form
{
    public List<Question> Questions { get; set; }
}
public class Question
{
    public string QuestionText { get; set; }
}

和问题的子类

public class TextBoxQuestion : Question
{
    public string TextAnswer { get; set; }
    public int TextBoxWidth { get; set; }
}

我还有一个视图,它将表单类型作为模型和两个显示模板,一个用于问题,一个用于 TextBoxQuestion。

//Views/Form/index.cshtml
@model Form
@Html.DisplayFor(m => m.Questions)

-

//Views/Shared/DisplayTemplates/Question.cshtml
@model Question
@if(Model is TextBoxQuestion)
{
    @Html.DisplayForModel("TextBoxQuestion")
}

-

//Views/Shared/DisplayTemplates/TextBoxQuestion.cshtml
@model TextBoxQuestion
<div>
    @Model.QuestionText
    @Html.TextBoxFor(m => m.TextAnswer)
</div>

当页面加载时,我的控制器创建一个 TextBoxQuestion 实例,将其添加到 Question 集合中,并将 Form 对象传递给视图。一切正常,文本框出现在页面上。

但是当我回发到控制器时,代码无法将问题识别为 TextBoxQuestion。它只将其视为父类型问题。

[HttpPost]
public ActionResult Index(Form f)
{
    foreach (var q in f.Questions)
    {
        if (q is TextBoxQuestion)
        {
            //code never gets here
        }
        else if (q is Form)
        {
            //gets here instead
        }
    }
}

有什么我想念的吗?

4

2 回答 2

1

模型绑定器将创建该方法期望的类型的实例。如果您想以这种方式使用子类和显示模板,您将需要编写自己的模型绑定器。

我建议检查一个或多个属性的存在以确定是否发布了一个TextBoxQuestionQuestion

模型粘合剂:

public class QuestionModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Question result;
        ValueProviderResult text = bindingContext.ValueProvider.GetValue("TextAnswer");
        if (text != null) // TextAnswer was submitted, we'll asume the user wants to create a TextBoxAnswer
            result = new TextBoxQuestion { TextAnswer = text.AttemptedValue /* Other attributes */ };
        else
            result = new Question();

        // Set base class attributes
        result.QuestionText = bindingContext.ValueProvider.GetValue("QuestionText").AttemptedValue;
        return result;
    }
}

然后将其连接到 Global.asax.cs:

ModelBinders.Binders.Add(typeof(Question), new QuestionModelBinder());
于 2012-11-13T20:12:04.190 回答
0

在我看来,您一次只问一个问题。因此,当您最有可能发布您的信息时,您只会发送一个问题,而不是一组问题。将您的方法更改为:

[HttpPost]
public ActionResult Index(Question q)
{
    if (q is TextBoxQuestion)
    {
        //proces TextBoxQuestion
    }
    else if (q is Question)
    {
        //process generic question
    }
}
于 2012-11-13T19:24:52.590 回答