属性 的 MVC 3 模型活页夹问题,它是继承对象的列表

Issue with MVC 3 model binder for propery which is a list of inherited objects

问题与此非常相似post How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects? 然而,我们没有尝试手动序列化字符串,而是尝试使用 MVC 3 中的模型绑定。所以这里是场景

[DataContract]
public class Company
{

    [DataMember]
    public List<Person> Employees { get; set; }
}

 [DataContract]
public class Person
{
     [DataMember]
     public string FirstName { get; set; }
     [DataMember]
     public string LastName { get; set; }
}

[DataContract]
[KnownType(typeof(Person))]
public class Employee : Person
{
    [DataMember]
    public string Department { get; set; }
    [DataMember]
    public string JobTitle { get; set; }
}

[DataContract]
[KnownType(typeof(Person))]
public class Artist : Person
{
    [DataMember]
    public string Skill { get; set; }
}

public JsonResult PopulateCompany()
{

    Company model = new Company();
    model.Employees = new List<Person>
    {
        new Employee(),
        new Employee(),
        new Artist(),
    };

    return Json(model, JsonRequestBehavior.AllowGet);
    // in the View the model is correctly deserialized. E.g. we can see the properties from Artist


}

public ActionResult PopulateCompany(Company model)
{
    // the returned model is also being populated except the Person object is being added to the Employees and we can no longer access the properties of Artist.
    return View(model);
}

谢谢。

模型绑定过程涉及首先初始化模型。在您的情况下,它使用 属性 List<Person> Employees 初始化 Company 的实例。根据回发的值,如果发现 key/value 对匹配 Person(例如 Persons[0].FirstName: "Ian"),则初始化 Person 的新实例及其属性已设置并添加到集合中。

DefaultModelBinder 无法知道您想要初始化不同的具体类型。

简单的解决方案是使用包含每种类型集合属性的视图模型(例如 public List<Employees> Employees { get; set; }; public List<Artist> Artists { get; set; }; 等)。

另一种(困难的)解决方案是创建一个自定义 ModelBinder,它将根据模型中的值生成具体类型。 This article(Abstract Model Binder 部分)是学习如何创建自定义 ModelBinder

的良好开端