考虑 Microsoft.AspNet.OData 中的复杂类型和属性

Accounting for Complex Types & Properties in Microsoft.AspNet.OData

我在获取要序列化的复杂对象时遇到问题。我发现这方面的例子很少,需要一些帮助。我有一个 POCO class 实现了 Class 属性 的接口,如下所示...

如何让 ODATA 识别属性中的复杂类型?

POCO CLASS:

public class ShakeoutDocument : Document, IDocument, IStateful
{
    public IObjectState ObjectState { get; set; } //<-- This property contains the instance (below)

    public int ShakeoutId { get; set; }

    public string SchedulingBatch { get; set; }

    [...] //<-- Other properties are omitted for brevity
}

IObjectState 属性 CLASS:
这是一个具体的 IObjectState 示例 class...

// Example of an IObjectState Instance
public class New : IObjectState
{
    public List<IObjectStateEvent> Events { get; set; }

    public string Name { get; set; }
}

EDM 配置:作为绑定函数:
使用此 EDM 模型配置 & Api...

modelBuilder.EntitySet<ShakeoutDocument>("ShakeoutDocument");

[HttpGet]
public ShakeoutDocument Get([FromODataUri] int id)
{
    var provider = Application.ShakeoutDocumentProvider as ShakeoutDocumentProvider;
    var entity = provider.Get(id);

    return entity;
}

生成以下异常...

"The given model does not contain the type 'New'."

EDM 配置:作为未绑定函数:
使用此 EDM 模型配置 & Api...

var getShakeoutDocument = modelBuilder.Function("GetShakeoutDocument").ReturnsFromEntitySet<ShakeoutDocument>("ShakeoutDocument");
getShakeoutDocument.Parameter<int>("id");

[ODataRoute("GetShakeoutDocument(id={id})")]
public IHttpActionResult GetShakeoutDocument([FromODataUri] int id)
{
    var provider = Application.ShakeoutDocumentProvider as ShakeoutDocumentProvider;
    var entity = provider.Get(id);

    return Ok(entity);
}

生成以下异常...

"The given model does not contain the type 'New'."

更新 EDM 配置:使用具体的新配置:
更新 EDM 模型配置...

modelBuilder.AddComplexType(typeof(New));

生成以下异常...

"A value was encountered that has a type name that is incompatible with the metadata. The value specified its type as 'New', but the type specified in the metadata is 'IObjectState'."

感谢任何帮助。

好的,经过大量搜索,我找到了答案here。基本上,您必须向 OData 描述任何给定 Complex 属性 的所有可能实现...即使是未绑定函数。

真正未绑定 应该 暗示正在使用标准 WebApi...但显然不是这种情况...因为此对象使用标准 WebApi 很好地序列化,但失败了使用 OData。

private static  IEdmModel GetEdmModel()
{
    var modelBuilder = new ODataConventionModelBuilder();

    // ENTITY SETS: Normal
    modelBuilder.EntitySet<tblDbcCommunications>("Communication");
    modelBuilder.EntitySet<tblDbcItems>("Item");
    modelBuilder.EntitySet<Meter>("Meter");
    modelBuilder.EntitySet<Product>("Product");
    modelBuilder.EntitySet<WarehouseMeter>("WarehouseMeter");
    modelBuilder.EntitySet<Shakeout>("Shakeout");
    modelBuilder.EntitySet<tblDbcCircuitOwner>("tblDbcCircuitOwner");

    // ENTITY SETS: Complex
    ConfigureComplexEntitySet(modelBuilder, modelBuilder.EntitySet<ShakeoutDocument>("ShakeoutDocument"));

    // KEY BINDINGS
    modelBuilder.EntityType<WarehouseMeter>().HasKey(x => x.METER_ID);

    // UNBOUND FUNCTIONS
    //  - Action    = Post
    //  - Function  = Get

    // WarehouseMeter
    var findPulseMeter = modelBuilder.Function("FindWarehouseMeter").ReturnsCollectionFromEntitySet<WarehouseMeter>("WarehouseMeter");
    findPulseMeter.Parameter<string>("search");

    // ShakeoutDocument
    var getShakeoutDocument = modelBuilder.Function("GetShakeoutDocument").ReturnsFromEntitySet<ShakeoutDocument>("ShakeoutDocument");
    getShakeoutDocument.Parameter<int>("id");

    // Product
    var listProduct = modelBuilder.Function("ListProducts").ReturnsCollectionFromEntitySet<Product>("Product");

    return modelBuilder.GetEdmModel();
}

private static EntitySetConfiguration<ShakeoutDocument> ConfigureComplexEntitySet(ODataConventionModelBuilder modelBuilder, EntitySetConfiguration<ShakeoutDocument> configuration)
{

    // Collection Properties
    configuration.EntityType.CollectionProperty(x => x.Seals);
    configuration.EntityType.CollectionProperty(x => x.Details);

    // Complex Properties
    configuration.EntityType.ComplexProperty(x => x.ObjectState);

    // Object State
    var newObjectState = modelBuilder.ComplexType<New>();
    newObjectState.DerivesFrom<IObjectState>();

    var submittedObjectState = modelBuilder.ComplexType<Submitted>();
    submittedObjectState.DerivesFrom<IObjectState>();

    // Object State Event
    var isNewObjectStateEvent = modelBuilder.ComplexType<IsNew>();
    isNewObjectStateEvent.DerivesFrom<IObjectStateEvent>();

    var isSubmittedObjectStateEvent = modelBuilder.ComplexType<IsSubmitted>();
    isSubmittedObjectStateEvent.DerivesFrom<IObjectStateEvent>();

    return configuration;
}