繁体   English   中英

OData v4 WebAPI 响应中的项目计数

[英]Items count in OData v4 WebAPI response

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

我需要这个数字来分页,所以它应该是过滤后的项目数,但在“跳过”和“顶部”之前。

I already tried passing '$inlinecount=allpages' and '$count=true' parameters in query options in url ( https://damienbod.wordpress.com/2014/06/13/web-api-and-odata-v4- query-functions-and-attribute-routing-part-2/ - “Example of $count”),但我来自 WebAPI 的响应始终只有查询结果(集合) - 整个响应如下所示:

[
    {
        "Name":"name1", 
        "age":5
    }, 
    {
        "Name":"name2", 
        "age":15
    }
]

响应中没有像“odata.count”这样的东西。

我还尝试在我的 WebAPI controller 操作中返回 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 with Odata NextPage and Count not appearing in the JSON response and 我删除了 [EnableQuery] 属性,现在我的响应看起来像:

{
    "Items":
    [
        {
            "Name":"name1", 
            "age":5
        }, 
        {
            "Name":"name2", 
            "age":15
        }
    ],
    "NextPageLink":null,
    "Count":null
}

但“计数”始终是 null。 :(


编辑:在我的 controller 的请求属性中调试和搜索计数值后,我发现正确的计数值位于名为“System.Web.OData.TotalCount”的属性中。 所以现在我从那个请求属性中提取这个值,我的 controller 看起来像这样:

 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); }

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

供将来参考(OData v4):

首先, $inlinecountOData 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));
}

注意: ApiController不支持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);
    }
}

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;
}

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

编码的uri:

http://localhost:<portnumber>/People/?%24count=true&%24skip=1&%24top=3

解码:

http://localhost:<portnumber>/People/?$count=true&$skip=1&$top=3

参考文献:

这就是我在oData v4中使用的:

Request.ODataProperties().NextLink, 

Request.ODataProperties().TotalCount

请您访问https://github.com/OData/ODataSamples/blob/master/Scenarios/TripPin,查看示例服务TripPin web api实现。 您可以按照机场控制器中的代码和代码http://services.odata.org/TripPinWebApiService/Airports的服务进行操作?$ count = true可以正确返回计数。

这也可以通过动作过滤器实现:

/// <summary>
/// Use this attribute whenever total number of records needs to be returned in the response in order to perform paging related operations at client side.
/// </summary>
public class PagedResultAttribute: ActionFilterAttribute
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="actionExecutedContext"></param>
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);
        if (actionExecutedContext.Response != null)
        {                
            dynamic responseContent=null;
            if (actionExecutedContext.Response.Content != null)
                responseContent = actionExecutedContext.Response.Content.ReadAsAsync<dynamic>().Result;
            var count = actionExecutedContext.Response.RequestMessage.ODataProperties().TotalCount;
            var res = new PageResult<dynamic>() {TotalCount=count,Items= responseContent };

            HttpResponseMessage message = new HttpResponseMessage();
            message.StatusCode = actionExecutedContext.Response.StatusCode;

            var strMessage = new StringContent(JsonConvert.SerializeObject(res), Encoding.UTF8, "application/json");
            message.Content = strMessage;
            actionExecutedContext.Response = message;               
        }           
    }
}

自定义PageResult类是:

public class PageResult<T>
{      
    public long? TotalCount { get; set; }
    public T Items { get; set; }
}

用法:

[PagedResult]
[EnableQuery()]  

如果您使用的是 OData 常规路由,则当您的路由不为 odata 所知时,不会返回 $odata.count。 添加 'app.UseODataRouteDebug();' 到您的 ConfigureServices 方法,然后调用“https://localhost:5001/$odata”。 如果您的路由不在 OData 路由表中,则 OData 不知道您的路由,并且您没有为要包含在 OData 常规路由中的 controller 和 EDM 类型使用正确的命名约定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM