【问题标题】:Asp.net WebApi OData V4 problems with nested $expands嵌套 $expands 的 Asp.net WebApi OData V4 问题
【发布时间】:2018-11-29 06:37:38
【问题描述】:

我有一个OData V4 超过Asp.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);
 }

序列化的值包含 entity4。

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

编辑#2:

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

我已经跳转到源代码,我可以看到 SerializerContext.Items 不包括它的项目中的 entity4 并且 SerializerContext.NavigationSource 为空。

具体来说,我使用的是System.Web.OData, Version=6.1.0.10907

【问题讨论】:

  • 你如何设置 MaxExpandDepth ?你能给我们看看控制器的代码吗?
  • @J.Loscos - 位于EnableQueryAttribute 内部,位于Get 方法之上。我知道我这样做是正确的,因为过去由于 MaxDepth 不支持异常,我需要将值修改为 3。
  • 您使用的是什么版本的 Microsoft.AspNet.OData?我用 6.1.0 版本做了一个快速测试,一个 4 级扩展查询没有任何问题
  • @J.Loscos - 是的,我使用的是 6.1.0。我正在使用 ILSpy 试图解决这个问题。正如我之前所说,生成的 SQL 返回第 4 级,调用 EnableQueryAttribute 内的 ApplyQuery 方法后生成的 IQueryable 也是如此。
  • @J.Loscos - 您能否将成功的 4 级 $expand 响应中的 odata.context 粘贴到此处?

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


【解决方案1】:

好的,所以我注意到问题是由于我的导航属性是 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 添加到我的导航属性中。

由于我的解决方案是一种通用存储库,因此我已将其添加到 Startup for All 导航属性中:

builder.OnModelCreating = mb => mb.StructuralTypes.SelectMany(s => s.NavigationProperties
            .Where(np => np.Multiplicity == EdmMultiplicity.Many)).Distinct().ForEach(np => np.Contained());

//......

var model = builder.GetEdmModel();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 2015-07-29
    • 2015-11-06
    • 2014-07-26
    • 1970-01-01
    相关资源
    最近更新 更多