1
votes

Im trying to write a generic PageResultthat I have added to a base controller.

    [EnableQuery]
    [HttpGet]
    [Route(""]
    public virtual PageResult<TListModel> Get(ODataQueryOptions<TListModel> options)
    {
        ODataQuerySettings settings = new ODataQuerySettings()
        {
            PageSize = 25,
        };

        IQueryable results = options.ApplyTo(DomainService.GetQueryable(), settings);
        var items = results as IQueryable<TListModel>;
      // return new PageResult<TListModel>(items, Request.ODataProperties().NextLink,DomainService.GetQueryable().Count());
        return new PageResult<TListModel>(items, Request.ODataProperties().NextLink, Request.ODataProperties().TotalCount);

    }

Now when I try call the api endpoint

/endpoint?$select=Title

I get an error

Value cannot be null.\ \ Parameter name: source

If I remove the ?$select=TitleI can call the api and the results are returned.

Is there something else I should be doing to enable this? The parameter name source....I have no idea what this is?

The full stacktrace

" at System.Linq.Queryable.Count[TSource](IQueryable1 source)\ \ at Api.EndPoints.BaseController5.Get(ODataQueryOptions1 options) in e:\\@Source\\Web\\Api\\.EndPoints\\BaseController.cs:line 62\ \ at lambda_method(Closure , Object , Object[] )\ \ at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\ \ at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\ \ at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary2 arguments, CancellationToken cancellationToken)\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\ \ at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\ \ at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ \ at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\ \ at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\ \ at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\ \ at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()"

2
This is because after ApplyTo method, results is not of type IQueryable<TListModel>, but a partial project collection of TListModel.Karata

2 Answers

0
votes

I upgraded my solution to the latest Web API version and this is marked obolete, but works.

    [HttpGet, Route("Get")]
    public PageResult<DiplomateModel> Get(int legalValue, string area =                                                     null, int? pageSize = 20,ODataQueryOptions<Model> options = null)
    {
        try
        {
            var ret = GetUsers(legalValue, area);
            var settings = new ODataQuerySettings
            {
                PageSize = pageSize
            };
            IQueryable results = options.ApplyTo(ret, settings);
            var uri = Request.GetNextPageLink();
            long? inLineCount = Request.GetInlineCount();
            var response = new PageResult<DiplomateModel>(results as IEnumerable<Model>,uri,inLineCount);
            return response;
        }
        catch (Exception ex)
        {
            LogError(ex);
            return null;
        }
    }
0
votes

Oh yea, the only reason your code does not work is because of the [EnableQuery] decorator. Remove that and you should be good to go. EnableQuery() will prevent your call from going thru. EnableQuery only protects the method from malicious requests, but if your signature is strongly typed, it should not be an issue.