我遇到问题让我的控制器在回发上识别子类模型。
我正在创建一个动态Web表单,其中包含存储在db中的字段元数据。对于我的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; }
}
我还有一个视图,它将一个Form类型作为Model和两个显示模板,一个用于Question,另一个用于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
}
}
}
我有什么遗失的吗?
答案 0 :(得分:1)
模型绑定器将创建该方法所期望的类型的实例。如果您想以这种方式使用子类和显示模板,则需要编写自己的模型绑定器。
我建议检查是否存在一个或多个属性,以确定是否发布了TextBoxQuestion
或Question
。
ModelBinder的:
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());
答案 1 :(得分:0)
在我看来,你只是一次只问一个问题。因此,当您发布最相似的信息时,您只发送一个而不是一组问题。将您的方法更改为:
[HttpPost]
public ActionResult Index(Question q)
{
if (q is TextBoxQuestion)
{
//proces TextBoxQuestion
}
else if (q is Question)
{
//process generic question
}
}