如何返回OData v4 HTTP响应中的项目数?
我需要这个数字来分页,所以它应该是过滤后的项目数,但是在'skip'和'top'之前。
我已经尝试在url(https://damienbod.wordpress.com/2014/06/13/web-api-and-odata-v4-queries-functions-and-attribute-routing-part-2/ - “$ count的示例”)的查询选项中传递'$ inlinecount = allpages'和'$ count = true'参数,但我的WebAPI响应总是只有查询结果(集合) - 整个响应看起来像:
[
{
"Name":"name1",
"age":5
},
{
"Name":"name2",
"age":15
}
]
回复中没有类似“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 with Odata NextPage and Count not appearing in the JSON response我删除了[EnableQuery]属性,现在我的回复如下:
{
"Items":
[
{
"Name":"name1",
"age":5
},
{
"Name":"name2",
"age":15
}
],
"NextPageLink":null,
"Count":null
}
但仍然“Count”始终为null。 :(
<小时/> 编辑:调试并在我的控制器中的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);
}
它工作正常,但我仍然不知道为什么我必须使用这样的解决方法。
答案 0 :(得分:8)
供将来参考(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));
}
属性附加到返回结果的方式:
ApiController
注意:强>
count
s不支持OData功能 不能包含$metadata
或ApiController
之类的内容。如果你选择 使用简单count
上面的方法是你应该使用的方式 返回ODataController
属性。
要完全支持OData功能,您应该通过以下方式实现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);
}
}
:
<强> PeopleController.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;
}
App_Start \ WebApiConfig.cs
http://localhost:<portnumber>/People/?%24count=true&%24skip=1&%24top=3
然后以这种方式访问您的OData Api(示例):
编码的uri:
http://localhost:<portnumber>/People/?$count=true&$skip=1&$top=3
解码:
CREATE TABLE public.portfolio (
id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('portfolio_id_seq'::regclass),
name CHARACTER VARYING(80) NOT NULL,
path CHARACTER VARYING(80) NOT NULL
);
CREATE UNIQUE INDEX portfolio_path_key ON portfolio USING BTREE ("4");
CREATE UNIQUE INDEX portfolio_name_key ON portfolio USING BTREE (name);
参考文献:
答案 1 :(得分:2)
这就是我使用的oData v4:
Request.ODataProperties().NextLink,
Request.ODataProperties().TotalCount
答案 2 :(得分:0)
请您在https://github.com/OData/ODataSamples/blob/master/Scenarios/TripPin查看示例服务TripPin web api实施。您可以按照机场控制器中的代码和代码http://services.odata.org/TripPinWebApiService/Airports的服务进行操作?$ count = true可以正确返回计数。
答案 3 :(得分:0)
这也可以通过动作过滤器来实现:
/// <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()]