В моем контроллере ODATA-v4 у меня есть следующий код:
var fn = reportModelBuilder.EntityType<CurrentTestResult>()
.Collection.Function("Breakdown").Returns<int>();
В CurrentTestResultController.cs у меня обманчиво просто:
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
[HttpGet]
public IHttpActionResult Breakdown()
{
var count = dataService.GetAll()
.Select(x => x.TestResultTypeId)
.Distinct()
.Count();
return Ok(count);
}
По сути, для всех сущностей CurrentTestResult
в коллекции он возвращает отдельные TestResultTypeId
, встречающиеся в наборе. (Это тривиальная операция, но я упростил реальный сценарий, который намного сложнее)
Это было легко сделать, но я не могу сначала отфильтровать коллекцию CurrentTestResult
, с которой он должен работать.
Этот запрос, который по умолчанию работает со всеми объектами CurrentTestResult
localhost/app/odatareport/CurrentTestResult/Default.Breakdown
возвращается
{
@odata.context: "http://localhost/app/odatareport/$metadata#Edm.Int32",
value: 5
}
(Правильный результат, есть 5 различных типов)
Однако этот запрос, который пытается сначала просто отфильтровать его, терпит неудачу.
localhost/app/odatareport/CurrentTestResult/Default.Breakdown?$top=2
возвращается
{
error: {
code: "",
message: "The query specified in the URI is not valid. The requested resource is not a collection. Query options $filter, $orderby, $count, $skip, and $top can be applied only on collections.",
innererror: {
message: "The requested resource is not a collection. Query options $filter, $orderby, $count, $skip, and $top can be applied only on collections.",
type: "Microsoft.OData.ODataException",
stacktrace:
" at System.Web.OData.EnableQueryAttribute.ValidateSelectExpandOnly(ODataQueryOptions queryOptions) at System.Web.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor, ODataQueryContext queryContext) at System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"
}
}
}
Насколько я понимаю конвейер ODATA, почему это не работает, имеет смысл. Метод контроллера вернет IQueryable, а затем будут применены фильтры ODATA $filter, $top и т. д.
Я хотел бы, чтобы функция работала с набором, который уже был отфильтрован.
Возможно ли то, что я пытаюсь сделать?
Я понимаю, что в самом методе Breakdown есть .GetAll(), но должен быть способ применить фильтрацию перед методом -
Иначе все это совершенно бессмысленно...