6

我正在使用 EntitySetController 创建一个 oData web api 控制器,一切正常,除了获取总记录数。

控制器定义如下:

public class MyODataController : EntitySetController<Entity1, int> where TEntity : class
{
    public override IQueryable<Entity1> Get()
    {
        return EntityDatabase.Get();
    }
}

当我通过以下方式呼叫计数时:

http://localhost:44789/oData/MyOData/$count

我收到错误:检测到无效操作。'$count' 不是可以绑定到 'Collection([Entity1 Nullable=False])' 的操作。

4

5 回答 5

14

不幸的是,Web API 还不支持 $count 开箱即用,尽管它应该在未来的版本中。同时,您仍然可以通过定义这些类来添加支持:

public class CountODataRoutingConvention : EntitySetRoutingConvention
{
    public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
    {
        if (controllerContext.Request.Method == HttpMethod.Get && odataPath.PathTemplate == "~/entityset/$count")
        {
            if (actionMap.Contains("GetCount"))
            {
                return "GetCount";
            }
        }
        return null;
    }
}

public class CountODataPathHandler : DefaultODataPathHandler
{
    protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment)
    {
        if (segment == "$count")
        {
            return new CountPathSegment();
        }
        return base.ParseAtEntityCollection(model, previous, previousEdmType, segment);
    }
}

public class CountPathSegment : ODataPathSegment
{
    public override string SegmentKind
    {
        get
        {
            return "$count";
        }
    }

    public override IEdmType GetEdmType(IEdmType previousEdmType)
    {
        return EdmCoreModel.Instance.FindDeclaredType("Edm.Int32");
    }

    public override IEdmEntitySet GetEntitySet(IEdmEntitySet previousEntitySet)
    {
        return previousEntitySet;
    }

    public override string ToString()
    {
        return "$count";
    }
}

在 MapODataRoute 中注册它们:

IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault();
routingConventions.Insert(0, new CountODataRoutingConvention());
config.Routes.MapODataRoute("OData", "odata", GetModel(), new CountODataPathHandler(), routingConventions);

在您的控制器中,添加此方法:

public HttpResponseMessage GetCount(ODataQueryOptions<TEntity> queryOptions)
{
    IQueryable<TEntity> queryResults = queryOptions.ApplyTo(Get()) as IQueryable<TEntity>;
    int count = queryResults.Count();
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = new StringContent(count.ToString(), Encoding.UTF8, "text/plain");
    return response;
}

为了避免必须将 GetCount() 复制到每个控制器,您可以定义一个派生自定义 GetCount 的 EntitySetController 的基类。

于 2013-05-20T14:23:19.900 回答
7

If you use the following:

http://localhost:44789/oData/MyOData?$inlinecount=allpages

then the total count will be included in your get return.

于 2013-05-20T15:02:04.127 回答
2

localhost:..../?$inlinecount=allpages&$skip=0&$top=0 我认为这是击球手。您不需要添加更多代码。

于 2015-01-26T10:44:14.373 回答
2

OData v4.0 的最新包 Web API 2.2 支持 $count。

于 2014-07-25T20:32:25.947 回答
0

一种选择是将 $top=0 与 $inlinecount=allpages 结合使用。有点解决方法,但我发现它很好用,我宁愿返回对象而不是单个整数值。这也适用于过滤器:

http://localhost:44789/oData/MyOData?$filter=MyFilter&$top=1&$inlinecount=allpages
于 2016-07-28T13:26:17.403 回答