OData v4 WebAPI响应中的项目计数

ana*_*aid 8 count odata asp.net-web-api

如何返回OData v4 HTTP响应中的项目数?

我需要这个数字来分页,所以它应该是过滤后的项目数,但是在'skip'和'top'之前.

我已经尝试在url中的查询选项中传递'$ inlinecount = allpages'和'$ count = true'参数(https://damienbod.wordpress.com/2014/06/13/web-api-and-odata-v4- queries-functions-and-attribute-routing-part-2 / - "$ count的示例"),但是我的WebAPI响应总是只有查询结果(集合) - 整个响应如下所示:

[
    {
        "Name":"name1", 
        "age":5
    }, 
    {
        "Name":"name2", 
        "age":15
    }
]
Run Code Online (Sandbox Code Playgroud)

响应中没有类似"odata.count"的内容.

我也尝试在我的WebAPI控制器操作中返回PageResult而不是IQueryable(如下所述:http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata- query-options#server-paging),但不推荐使用Request.GetInlineCount(),其值始终为null.

有任何想法吗?

[更新]我刚刚发现了同样的问题:WebApi与Odata NextPage和Count没有出现在JSON响应中,我删除了[EnableQuery]属性,现在我的响应如下:

{
    "Items":
    [
        {
            "Name":"name1", 
            "age":5
        }, 
        {
            "Name":"name2", 
            "age":15
        }
    ],
    "NextPageLink":null,
    "Count":null
}
Run Code Online (Sandbox Code Playgroud)

但仍然"计数"始终为空.:(


编辑:调试并在我的控制器中的Request属性中搜索计数值后,我发现正确的Count值位于名为"System.Web.OData.TotalCount"的属性中.所以现在我从该请求属性中提取此值,我的控制器看起来像这样:

public PageResult<People> Get(ODataQueryOptions<People> queryOptions)
{
    var query = _context.People.OrderBy(x => x.SomeProperty);
    var queryResults = (IQueryable<People>)queryOptions.ApplyTo(query);
    long cnt = 0;
    if (queryOptions.Count != null)
        cnt = long.Parse(Request.Properties["System.Web.OData.TotalCount"].ToString());

    return new PageResult<People>(queryResults, null, cnt);
}
Run Code Online (Sandbox Code Playgroud)

它工作正常,但我仍然不知道为什么我必须使用这样的解决方法.

Cod*_*ist 9

供将来参考(OData v4):

首先$inlinecount它不受支持,OData v4所以你应该使用它$count=true.

其次,如果你有一个正常ApiController,你返回一个类似IQueryable<T>这样的类型是你可以将count属性附加到返回的结果:

using System.Web.OData;
using System.Web.OData.Query;
using System.Web.OData.Extensions;

//[EnableQuery] // -> If you enable globally queries does not require this decorator!
public IHttpActionResult Get(ODataQueryOptions<People> queryOptions)
{
    var query = _peopleService.GetAllAsQueryable(); //Abstracted from the implementation of db access. Just returns IQueryable<People>
    var queryResults = (IQueryable<People>)queryOptions.ApplyTo(query);
    return Ok(new PageResult<People>(queryResults, Request.ODataProperties().NextLink, Request.ODataProperties().TotalCount));
}
Run Code Online (Sandbox Code Playgroud)

注意:ApiController s 不支持OData功能,因此您不能使用count$metadata.如果您选择使用简单ApiController,上面的方式是您应该用来返回count房产的方式.


要完全支持OData功能,您应该ODataController按以下方式实现:

PeopleController.cs

using System.Web.OData;
using System.Web.OData.Query;

public class PeopleController : ODataController
{
    [EnableQuery(PageSize = 10, AllowedQueryOptions = AllowedQueryOptions.All)]
    public IHttpActionResult Get()
    {
        var res = _peopleService.GetAllAsQueryable();
        return Ok(res);
    }
}
Run Code Online (Sandbox Code Playgroud)

App_Start\WebApiConfig.cs

public static void ConfigureOData(HttpConfiguration config)
{
    //OData Models
    config.MapODataServiceRoute(routeName: "odata", routePrefix: null, model: GetEdmModel(), batchHandler: new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
    config.EnsureInitialized();
}

private static IEdmModel GetEdmModel()
{
    var builder = new ODataConventionModelBuilder
    {
        Namespace = "Api",
        ContainerName = "DefaultContainer"
    };
    builder.EntitySet<People>("People").EntityType.HasKey(item => item.Id); //I suppose the returning list have a primary key property(feel free to replace the Id key with your key like email or whatever)
    var edmModel = builder.GetEdmModel();
    return edmModel;
}
Run Code Online (Sandbox Code Playgroud)

然后以这种方式访问​​您的OData Api(示例):

编码的uri:

http://localhost:<portnumber>/People/?%24count=true&%24skip=1&%24top=3
Run Code Online (Sandbox Code Playgroud)

解码:

http://localhost:<portnumber>/People/?$count=true&$skip=1&$top=3
Run Code Online (Sandbox Code Playgroud)

参考文献:


Qia*_*nLi 1

请您查看示例服务 TripPin Web API 实现,网址为https://github.com/OData/ODataSamples/blob/master/Scenarios/TripPin。您可以按照Airports控制器中的代码进行操作,并且带有代码http://services.odata.org/TripPinWebApiService/Airports ?$count=true的服务可以正确返回计数。