考虑 Microsoft.AspNet.OData 中的复杂类型和属性
Accounting for Complex Types & Properties in Microsoft.AspNet.OData
我在获取要序列化的复杂对象时遇到问题。我发现这方面的例子很少,需要一些帮助。我有一个 POCO class 实现了 Class 属性 的接口,如下所示...
- 问题是...OData 无法序列化 IObjectState 属性
如何让 ODATA 识别属性中的复杂类型?
- 请记住 IObjectState 是一个非实体 class 并且没有键
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;
}
我在获取要序列化的复杂对象时遇到问题。我发现这方面的例子很少,需要一些帮助。我有一个 POCO class 实现了 Class 属性 的接口,如下所示...
- 问题是...OData 无法序列化 IObjectState 属性
如何让 ODATA 识别属性中的复杂类型?
- 请记住 IObjectState 是一个非实体 class 并且没有键
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;
}