@ Html.EditorFor不会将特定类型返回给控制器

时间:2015-01-16 07:54:19

标签: c# model-view-controller asp.net-core-mvc

让我们假设以下简化的类结构:

public class Parent
{
    public int ID { get; set; }
}

public class ChildA : Parent
{
    public string Name { get; set; }
}

public class ChildB : Parent
{
    public DateTime Date { get; set; }
}

public class ChildC : Parent
{
    public int NumericData { get; set; }
}

public class ViewModel
{
    public List<Parent> ChildElements { get; set; }
}

正如您所看到的,在我的视图模型中,我有一个对象列表,但这些对象可以是不同类型的。

现在,我发现编辑器模板在这种情况下运行良好 - @Html.EditorFor()根据需要选择正确的编辑器,具体取决于列表中元素的类型。

然而,我无法从用户那里获得有意义的数据到控制器。提交表单后,视图模型包含Parent元素列表(不是特定的子类型)。更糟糕的是 - 每个Child类特有的属性都会丢失!

如何将子类型的所有信息返回给控制器?

1 个答案:

答案 0 :(得分:1)

当数据发布到控制器时,MVC框架处理请求数据与模型的绑定。看看this link

当它试图实例化你的ViewModel时,它可能正在为你的Parent类使用默认的无参数构造函数,无论发送回的实际数据是什么,它都不会将它分配给属性,因为它们不会; t存在于Parent类中。

您可以创建自己的custom model binder,这可能会解决您的问题。或者您可以在Parent类中创建所有属性,并具有不同的命名EditorTemplates。

@Html.EditorFor(x => Model.Parent, "ChildATemplate")

@Html.EditorFor(x => Model.Parent, "ChildBTemplate") 

作为一般规则,坚持规则是一个好主意,即使一开始就感觉像是重复,一个视图,一个ViewModel&#34;它清楚地说明了从服务器发送的数据到底是什么数据以及确切返回的数据。

如果父母&#39;表示一个复杂的对象,可能是一个持久存储在数据库中并与多个视图交互的对象,然后您可以始终拥有一个中间层来处理从视图模型到复杂类的数据转换。

编辑 - 回应关于调查问题的评论

为什么不接受你需要复制一些共享值,并为每个问题类型创建一个类,而不是使用继承?

public class QuestionTypeA 
{
    public int ID { get; set;}
    public string Name { get; set; }
}

public class QuestionTypeB
{
    public int ID { get; set;}
    public DateTime Date { get; set; }
}

public class QuestionTypeC
{
    public int ID { get; set;}
    public int NumericData { get; set; }
}

public class ViewModel
{
    public List<QuestionTypeA> QuestionAs { get; set; }
    public List<QuestionTypeB> QuestionBs { get; set; }
    public List<QuestionTypeC> QuestionCs { get; set; }
}
相关问题