我在OData V4
(Asp.net WebApi
)上有一个OWIN
。
一切正常,除了当我尝试查询4级$expand
时。
我的查询看起来像:
http://domain/entity1($expand=entity2($expand=entity3($expand=entity4)))
我没有收到任何错误,但是我的回应中没有计划最后的扩展。
更多信息:
MaxExpandDepth
设置为10。EntitySets
。 ODataConventionModelBuilder
。 $expands
,但它们也无法正常工作。 编辑:
我已经覆盖了
OnActionExecuted
:public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
var objectContent = actionExecutedContext.Response.Content as ObjectContent;
var val = objectContent.Value;
var t = Type.GetType("System.Web.OData.Query.Expressions.SelectExpandWrapperConverter, System.Web.OData");
var jc = Activator.CreateInstance(t) as JsonConverter;
var jss = new JsonSerializerSettings();
jss.Converters.Add(jc);
var ser = JsonConvert.SerializeObject(val, jss);
}
序列化的值包含entity4。
我仍然不知道哪个组件会删除管道中的entity4。
编辑#2:
我已经在
DefaultODataSerializerProvider
和所有其他ODataEdmTypeSerializer's
上创建了一个适配器。我看到在此过程中,entity4的$expand
存在,并且在该navigationProperty(entity4)上调用ODataResourceSerializer.CreateNavigationLink
方法时,该方法将返回null。我跳到了源代码中,可以看到
SerializerContext.Items
的项目中未包含entity4,并且SerializerContext.NavigationSource
为null。具体来说,我使用的是
System.Web.OData, Version=6.1.0.10907
。 最佳答案
好的,所以我注意到问题是由于我的导航属性为EdmUnknownEntitySet
类型,并且导航属性查找返回null(源代码带有错误的TODO ..):
/// <summary>
/// Finds the entity set that a navigation property targets.
/// </summary>
/// <param name="property">The navigation property.</param>
/// <returns>The entity set that the navigation propertion targets, or null if no such entity set exists.</returns>
/// TODO: change null logic to using UnknownEntitySet
public override IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty property)
{
return null;
}
所以我知道我的问题出在
EdmUnknownEntitySet
上。我深入研究了代码,发现需要将
ContainedAttribute
添加到我的导航属性中。由于我的解决方案属于通用存储库,因此已将其添加到“所有启动”导航属性中:
builder.OnModelCreating = mb => mb.StructuralTypes.SelectMany(s => s.NavigationProperties
.Where(np => np.Multiplicity == EdmMultiplicity.Many)).Distinct().ForEach(np => np.Contained());
//......
var model = builder.GetEdmModel();