当我发布的ShakeoutDocument
中没有填充集合时,OData Serializer
会理解JSON
并正确地填充ODataActionParameters
。
但是,当我将子记录添加到ShakeoutDocument's
集合属性之一中时,Odata Controller's
ODataActionParameters
参数为null。我将其范围缩小到OData EDM Model Configuration
。
喜欢的班级:
这些集合是“详细信息和印章”(如下)
public class ShakeoutDocument : Document
{
public IObjectState ObjectState { get; set; } //<-- This "registers" just fine?
public int ShakeoutId { get; set; }
public string SchedulingBatch { get; set; }
public int? ProductId { get; set; }
public decimal? Gravity { get; set; }
public decimal? Temperature { get; set; }
public decimal? SedimentAndWater { get; set; }
public DateTime? BatchEndDate { get; set; }
public DateTime? SampleWorkedDate { get; set; }
public string Witness { get; set; }
public string Notes { get; set; }
public List<ShakeoutDetail> Details { get; set; } //<-- How do I "register" this?
public List<ShakeoutSeal> Seals { get; set; } //<-- How do I "register" this?
}
我当前的EDM配置看起来像:
我尝试了各种定义为HERE的方法。奇怪的是... IObjectState
注册得很好。
private static IEdmModel GetEdmModel()
{
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.Namespace = "Pulse";
modelBuilder.ContainerName = "PulseContainer";
// -------------------
// ENTITY SETS: Normal
modelBuilder.EntitySet<tblDbcCommunications>("Communication");
modelBuilder.EntitySet<tblDbcItems>("Item");
modelBuilder.EntitySet<Meter>("Meter");
modelBuilder.EntitySet<Product>("Products");
modelBuilder.EntitySet<WarehouseMeter>("WarehouseMeters");
modelBuilder.EntitySet<tblDbcCircuitOwner>("tblDbcCircuitOwner");
modelBuilder.EntitySet<ShakeoutDetail>("ShakeoutDetails");
modelBuilder.EntitySet<ShakeoutSeal>("ShakeoutSeals");
// --------------------
// ENTITY SETS: Complicated
ConfigureEntitySet(modelBuilder, modelBuilder.EntitySet<ShakeoutDocument>("ShakeoutDocuments"));
// ------------
// KEY BINDINGS: Non-Entity
//
// - This area is for DTO's (there is no EF Configuration for these)
modelBuilder.EntityType<WarehouseMeter>().HasKey(x => x.METER_ID);
// -----------------
// UNBOUND FUNCTIONS
// - Action = Post
// - Function = Get
//----
// ShakeoutDocument
var createShakeoutDocument = modelBuilder.Action("CreateShakeoutDocument").ReturnsFromEntitySet<ShakeoutDocument>("ShakeoutDocument");
createShakeoutDocument.CollectionParameter<int>("identities");
var deleteShakeoutDocument = modelBuilder.Action("DeleteShakeoutDocument").ReturnsFromEntitySet<ShakeoutDocument>("ShakeoutDocument");
deleteShakeoutDocument.Parameter<int>("key");
var getShakeoutDocument = modelBuilder.Function("GetShakeoutDocument").ReturnsFromEntitySet<ShakeoutDocument>("ShakeoutDocument");
getShakeoutDocument.Parameter<int>("key");
var saveShakeoutDocument = modelBuilder.Action("SaveShakeoutDocument").ReturnsFromEntitySet<ShakeoutDocument>("ShakeoutDocument");
saveShakeoutDocument.Parameter<ShakeoutDocument>("document");
//----
// ShakeoutDetail
var saveShakeoutDetail = modelBuilder.Action("SaveShakeoutDetail").ReturnsFromEntitySet<ShakeoutDetail>("ShakeoutDetail");
saveShakeoutDetail.Parameter<ShakeoutDetail>("detail");
//----
// ShakeoutSeal
var saveShakeoutSeal = modelBuilder.Action("SaveShakeoutSeal").ReturnsFromEntitySet<ShakeoutSeal>("ShakeoutSeal");
saveShakeoutSeal.Parameter<ShakeoutSeal>("seal");
//----
// Product
var listProduct = modelBuilder.Function("ListProducts").ReturnsCollectionFromEntitySet<Product>("Product");
//----
// WarehouseMeter
var findPulseMeter = modelBuilder.Function("FindWarehouseMeter").ReturnsCollectionFromEntitySet<WarehouseMeter>("WarehouseMeter");
findPulseMeter.Parameter<string>("search");
return modelBuilder.GetEdmModel();
}
private static EntitySetConfiguration<ShakeoutDocument> ConfigureEntitySet(ODataConventionModelBuilder modelBuilder, EntitySetConfiguration<ShakeoutDocument> configuration)
{
// ---------------------
// Collection Properties
// FAILS: Meaning, the collection is not serialized & returned
//var details = configuration.EntityType.CollectionProperty(x => x.Details);
//var seals = configuration.EntityType.CollectionProperty(x => x.Seals);
// FAILS: Meaning, the collection is not serialized & returned
//configuration.HasManyBinding(x => x.Details, "ShakeoutDetail");
//configuration.HasManyBinding(x => x.Seals, "ShakeoutSeal");
// ------------------
// Complex Properties
configuration.EntityType.ComplexProperty(x => x.ObjectState);
// IObjectState
var objectState = modelBuilder.ComplexType<IObjectState>();
objectState.CollectionProperty(x => x.Events);
// 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;
}
发送此JSON作品:
如果我SEND
,这JSON
,而没有填充Details&Seals集合,则会正确序列化。
如果我填充“ Details&Seals”集合,则参数为NULL。
{
"DocumentTypeId": 1,
"GlobalId": "e8c9d71d-2773-e911-b71a-8cdcd4471a95",
"ParentId": null,
"AuthorId": 1,
"PublisherId": null,
"RevisionNumber": 0,
"PublishedDate": null,
"IsActive": true,
"Id": 44,
"CreateUserId": "(removed)",
"CreateDate": "2019-05-10T08:25:46.31-05:00",
"UpdateUserId": "(removed)",
"UpdateDate": "2019-05-10T08:25:46.31-05:00",
"ShakeoutId": 44,
"SchedulingBatch": null,
"ProductId": null,
"Gravity": null,
"Temperature": null,
"SedimentAndWater": null,
"BatchEndDate": null,
"SampleWorkedDate": null,
"Witness": null,
"Notes": null,
"Seals": [],
"Details": [],
"ObjectState": {
"@odata.type": "#Namespace...ShakeoutDocument.New",
"Name": "New",
"Events": [
{
"@odata.type": "#Namespace...ShakeoutDocument.IsNew",
"Name": "IsNew"
}
]
}
}
接收失败:
这显示了从服务发送回客户端的对象和客户端接收的JSON。
无限功能外观:
为了完整起见,我将其包括在内...
[HttpPost]
[ODataRoute("SaveShakeoutDocument")]
public IHttpActionResult SaveDocument(ODataActionParameters parameters)
{
var provider = Application.ShakeoutDocumentProvider;
var document = null as ShakeoutDocument;
try
{
document = provider.Get(key);
}
catch (Exception ex)
{
LogException(ex);
throw;
}
return Ok(document);
}
更新1:
$ MetaData似乎了解集合类型...
<EntityType Name="ShakeoutDocument" BaseType="Pulse.Document">
<Property Name="ObjectState" Type="Pulse.IObjectState" Nullable="false"/>
<Property Name="ShakeoutId" Type="Edm.Int32" Nullable="false"/>
<Property Name="SchedulingBatch" Type="Edm.String"/>
<Property Name="ProductId" Type="Edm.Int32"/>
<Property Name="Gravity" Type="Edm.Decimal"/>
<Property Name="Temperature" Type="Edm.Decimal"/>
<Property Name="SedimentAndWater" Type="Edm.Decimal"/>
<Property Name="BatchEndDate" Type="Edm.DateTimeOffset"/>
<Property Name="SampleWorkedDate" Type="Edm.DateTimeOffset"/>
<Property Name="Witness" Type="Edm.String"/>
<Property Name="Notes" Type="Edm.String"/>
<NavigationProperty Name="Details" Type="Collection(Pulse.ShakeoutDetail)"/>
<NavigationProperty Name="Seals" Type="Collection(Pulse.ShakeoutSeal)"/>
</EntityType>
更新2:
我只是注意到... ShakeoutDetails和ShakeoutDetail的NavigationPropertyBinding为“ Meter” ...在ShakeoutDocument中不存在(并且永远不会包含在内,因为这是不是实体的模型)。
<?xml version="1.0" encoding="UTF-8"?>
<EntityContainer Name="PulseContainer">
<EntitySet Name="Communication" EntityType="Pulse.tblDbcCommunications" />
<EntitySet Name="Item" EntityType="Pulse.tblDbcItems" />
<EntitySet Name="Meter" EntityType="Pulse.Meter" />
<EntitySet Name="Products" EntityType="Pulse.Product" />
<EntitySet Name="WarehouseMeters" EntityType="Pulse.WarehouseMeter" />
<EntitySet Name="tblDbcCircuitOwner" EntityType="Pulse.tblDbcCircuitOwner" />
<EntitySet Name="ShakeoutDetails" EntityType="Pulse.ShakeoutDetail">
<NavigationPropertyBinding Path="Meter" Target="Meter" />
</EntitySet>
<EntitySet Name="ShakeoutSeals" EntityType="Pulse.ShakeoutSeal" />
<EntitySet Name="ShakeoutDocuments" EntityType="Pulse.ShakeoutDocument" />
<EntitySet Name="ShakeoutDocument" EntityType="Pulse.ShakeoutDocument" />
<EntitySet Name="ShakeoutDetail" EntityType="Pulse.ShakeoutDetail">
<NavigationPropertyBinding Path="Meter" Target="Meter" />
</EntitySet>
<EntitySet Name="ShakeoutSeal" EntityType="Pulse.ShakeoutSeal" />
<EntitySet Name="Product" EntityType="Pulse.Product" />
<EntitySet Name="WarehouseMeter" EntityType="Pulse.WarehouseMeter" />
<ActionImport Name="CreateShakeoutDocument" Action="Pulse.CreateShakeoutDocument" EntitySet="ShakeoutDocument" />
<ActionImport Name="DeleteShakeoutDocument" Action="Pulse.DeleteShakeoutDocument" EntitySet="ShakeoutDocument" />
<FunctionImport Name="GetShakeoutDocument" Function="Pulse.GetShakeoutDocument" EntitySet="ShakeoutDocument" IncludeInServiceDocument="true" />
<ActionImport Name="SaveShakeoutDocument" Action="Pulse.SaveShakeoutDocument" EntitySet="ShakeoutDocument" />
<ActionImport Name="SaveShakeoutDetail" Action="Pulse.SaveShakeoutDetail" EntitySet="ShakeoutDetail" />
<ActionImport Name="SaveShakeoutSeal" Action="Pulse.SaveShakeoutSeal" EntitySet="ShakeoutSeal" />
<FunctionImport Name="ListProducts" Function="Pulse.ListProducts" EntitySet="Product" IncludeInServiceDocument="true" />
<FunctionImport Name="FindWarehouseMeter" Function="Pulse.FindWarehouseMeter" EntitySet="WarehouseMeter" IncludeInServiceDocument="true" />
</EntityContainer>
答案 0 :(得分:0)
根据您的最新更新,我认为导航属性绑定很有趣。
它不能解决仪表问题,您应该注意https://odata.github.io/WebApi/13-03-NavigationPropertyBindingWithComplexType/ (如果需要,还可以查看“瞬时动作”)