EF:如何反序列化从抽象类继承的对象?

时间:2017-11-01 13:57:33

标签: c# entity-framework asp.net-web-api2 abstract-class

是否可以反序列化从Abstract Class继承的对象?

我有以下内容:

public abstract partial class Item
{
  public Item() { }
  public int ItemID { get; set; }
  public Nullable<int> ObjectStateID { get; set; }
}


public abstract partial class Appointment : Item
{
  public Appointment() { }
  public string AppointmentDescription { get; set; }
}

public partial class AppointedActivity : Appointment
{
    public Nullable<int> AppointedActivityID { get; set; }
}

public partial class AppointedDevice : Appointment
{
    public Nullable<int> AppointedDeviceID { get; set; }
}

我有一个控制器应该POST Item s:

public Item PostItem([FromBody]Item item)
{
  // item is always null here.
  return item;
}

我遇到的问题是,无论我的身体内容是什么,控制器中的项目始终为空。

发送到控制器的JSON示例:

{
  "ObjectStateID": 1,
  "AppointmentDescription": "test",
  "AppointedActivityID": 90902 // Valid Activity ID.
}

我使用的是实体框架,我不确定该代码有什么问题。

谢谢!

2 个答案:

答案 0 :(得分:1)

您不能将抽象类型作为默认模型绑定器的参数传递给控制器​​。因为模型绑定器在创建此参数的实例时会出错。

如果您想为此类型创建自己的自定义模型装订器;

public class ItemModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var values = (ValueProviderCollection) bindingContext.ValueProvider;
        var itemId = (int) values.GetValue("ItemId").ConvertTo(typeof (int));
        var objectStateId = (int?) values.GetValue("ObjectStateId").ConvertTo(typeof(int));

        //Make desicion and create the real type instance Appointment, AppointedActivity or AppointedDevice
        return (Item) new Appointment { ItemId= itemId, ObjectStateId = objectStateId };
    }
}

在Global.asax;

ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(Item), new ItemModelBinder()));

答案 1 :(得分:0)

我最终在thisthis上建立了我的解决方案,并创建了一个使用Contract Resolver的自定义ItemResolver

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        switch ((ResourceKind)item["ResourceKind"].Value<int>())
        {
            case ResourceKind.ACTIVITY:
                return item.ToObject<AppointedActivity>();
            case ResourceKind.CONSUMABLE:
                return item.ToObject<AppointedConsumable>();
            case ResourceKind.DEVICE:
                return item.ToObject<AppointedDevice>();
            default:
                throw new Exception("Invalid ResourceType");
        }
    }