【问题标题】:OData, Net5: How to implement $count when controllers return entities of multiple typesOData,Net5:当控制器返回多种类型的实体时如何实现 $count
【发布时间】:2021-12-14 23:51:14
【问题描述】:

我正在将 OData 添加到 .Net5 中的现有大型 API,其中每个控制器中的操作方法返回不同的类型(例如 OrganizationFull、OrganizationList 等)

这是可行的,只是响应不包含 OData 元数据,例如 $count。所以当消费者调用 /api/OrganizationList?$count=true 时,它​​不会得到计数。

我知道要获取此元数据,我必须添加一个 EDM 模型,如下所示:

// Startup.cs

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers()
                .AddOData(opt => opt.Select().Filter().Count().SetMaxTop(10).AddRouteComponents("odata", GetEdmModel()))


        IEdmModel GetEdmModel()
        {
            var odataBuilder = new ODataConventionModelBuilder();

            odataBuilder.EntitySet<OrganizationFull>(nameof(Organization));
            odataBuilder.EntitySet<OrganizationList>(nameof(Organization)); // throws
            return odataBuilder.GetEdmModel();
        }


这里我指定了 2 个 EntitySet,一个对应于从 OrganizationController 返回的每个实体类型。

但是,这会引发异常“实体集 'Organization' 已配置有不同的 EntityType ('OrganizationFull')。”。如果我删除 OrganizationList 的 EntitySet,当我到达 List 端点时,我会得到 404。

如何让我的端点返回 $count 元数据,同时保留我的 API(从一个控制器返回多个实体类型)?

或者,有没有办法从 OData 基础架构中获取操作方法中的计数?在这种情况下,我可以在响应标头中返回它。

【问题讨论】:

标签: asp.net-core odata .net-5


【解决方案1】:

经过一番挖掘,我找到了一种从 OData 库中获取计数的方法,而无需为其提供 EDM 模型,也无需更改 API 的 JSON 响应(即,不添加 OData 元数据)。

这适用于 Microsoft.AspNetCore.OData 版本 8.0.1。

事实证明,这个库公开的 EnableQueryAttribute 过滤器的 OnActionExecuted 方法将计数与 http 上下文相关联。你可以重写这个方法,检索计数,然后用它做你想做的事情(比如创建一个响应头):

public partial class EnableQueryWithCountAttribute: EnableQueryAttribute
{
    public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);

        HttpContext context = actionExecutedContext.HttpContext;

        // TotalCount will be null if 1) Count is not enabled during startup; and 2) if
        // $count=true is not used in the url.

        long? count = context.Request.ODataFeature().TotalCount;
        if (count.HasValue)
        {
            // Here you could do something with count, 
            // such as adding it to the response using a response header.
        }
    }
}

然后,您将使用新属性而不是 EnableQuery 来装饰端点。例如:

[EnableQueryWithCount]
public virtual ActionResult<IQueryable<T>> Get()
{
    ...
}

【讨论】:

    【解决方案2】:

    尝试添加.Count()AddOData方法调用:

               .AddOData(opt => opt.Select().Filter().Count().SetMaxTop(10).AddRouteComponents("odata", GetEdmModel()))
    

    【讨论】:

    • 你是对的,.Count() 丢失了。更新了我的问题。然而,即使添加了这个,问题仍然存在:要获得计数,我仍然需要添加 EDM 模型。当我这样做时,属性路由不再起作用,您不能在同一个控制器中使用不同的操作方法返回不同的模型。
    • @user1147862 你有完整的例子,有控制器吗?现在看起来问题在于实体集的名称冲突,不同的实体集名称使用相同的名称。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多