嵌套$ expand的Asp.net WebApi OData V4问题

时间:2018-06-20 07:47:13

标签: c# asp.net-web-api odata

我在OData V4Asp.net WebApi)上有OWIN

除我尝试查询4级$expand之外,其他所有方法都很好。

我的查询如下:

http://domain/entity1($expand=entity2($expand=entity3($expand=entity4)))

我没有收到任何错误,但是我的回复中没有计划最后的扩展。

更多信息:

  1. 我已将MaxExpandDepth设置为10。
  2. 我所有的实体都是EntitySets
  3. 我正在使用ODataConventionModelBuilder
  4. 我打开了一个SQL分析器,可以看到查询(和结果)是正确的。这是执行查询后发生的一些过滤器。
  5. 我已经在网上搜索,没有找到合适的内容。
  6. 我尝试了不同的实体4级$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);
 }

序列化的值包含实体4。

我仍然不知道哪个组件会删除管道中的entity4。

编辑#2:

我已经在DefaultODataSerializerProvider和所有其他ODataEdmTypeSerializer's上创建了一个适配器。我看到在此过程中,entity4的$expand存在,并且在该navigationProperty(entity4)上调用了ODataResourceSerializer.CreateNavigationLink方法时,它返回了null。

我跳到源代码中,可以看到SerializerContext.Items的项目中未包含实体4,而SerializerContext.NavigationSource为空。

要具体说明版本,我使用的是System.Web.OData, Version=6.1.0.10907

1 个答案:

答案 0 :(得分:3)

好吧,所以我注意到问题是由于我的导航属性为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();