Reconstructing an ODataQueryOptions object and GetInlineCount returning null

asp.net-web-apic#-4.0odata

In an odata webapi call which returns a PageResult I extract the requestUri from the method parameter, manipulate the filter terms and then construct a new ODataQueryOptions object using the new uri.

(The PageResult methodology is based on this post:
http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options )

Here is the raw inbound uri which includes %24inlinecount=allpages

http://localhost:59459/api/apiOrders/?%24filter=OrderStatusName+eq+'Started'&filterLogic=AND&%24skip=0&%24top=10&%24inlinecount=allpages&_=1376341370337

Everything works fine in terms of the data returned except Request.GetInLineCount returns null.

This 'kills' paging on the client side as the client ui elements don't know the total number of records.

There must be something wrong with how I'm constructing the new ODataQueryOptions object.

Please see my code below. Any help would be appreciated.

I suspect this post may contain some clues https://stackoverflow.com/a/16361875/1433194 but I'm stumped.

public PageResult<OrderVm> Get(ODataQueryOptions<OrderVm> options)
    {

        var incomingUri = options.Request.RequestUri.AbsoluteUri;

//manipulate the uri here to suit the entity model   
//(related to a transformation needed for enumerable type OrderStatusId )
//e.g. the query string may include %24filter=OrderStatusName+eq+'Started' 
//I manipulate this to %24filter=OrderStatusId+eq+'Started'

        ODataQueryOptions<OrderVm> options2;

        var newUri = incomingUri;  //pretend it was manipulated as above

        //Reconstruct the ODataQueryOptions with the modified Uri

        var request = new HttpRequestMessage(HttpMethod.Get, newUri);

        //construct a new options object using the new request object
        options2 = new ODataQueryOptions<OrderVm>(options.Context, request);

        //Extract a queryable from the repository.  contents is an IQueryable<Order>
        var contents = _unitOfWork.OrderRepository.Get(null, o => o.OrderByDescending(c => c.OrderId), "");

        //project it onto the view model to be used in a grid for display purposes
        //the following projections etc work fine and do not interfere with GetInlineCount if
        //I avoid the step of constructing and using a new options object
        var ds = contents.Select(o => new OrderVm
        {
            OrderId = o.OrderId,
            OrderCode = o.OrderCode,
            CustomerId = o.CustomerId,
            AmountCharged = o.AmountCharged,
            CustomerName = o.Customer.FirstName + " " + o.Customer.LastName,
            Donation = o.Donation,
            OrderDate = o.OrderDate,
            OrderStatusId = o.StatusId,
            OrderStatusName = ""
        });

        //note the use of 'options2' here replacing the original 'options'
        var settings = new ODataQuerySettings()
        {
            PageSize = options2.Top != null ? options2.Top.Value : 5
        };

        //apply the odata transformation
        //note the use of 'options2' here replacing the original 'options'    
        IQueryable results = options2.ApplyTo(ds, settings);

        //Update the field containing the string representation of the enum
        foreach (OrderVm row in results)
        {
            row.OrderStatusName = row.OrderStatusId.ToString();
        }

        //get the total number of records in the result set 
        //THIS RETURNS NULL WHEN USING the 'options2' object - THIS IS MY PROBLEM
        var count = Request.GetInlineCount();

        //create the PageResult object
        var pr = new PageResult<OrderVm>(
            results as IEnumerable<OrderVm>,
            Request.GetNextPageLink(),
            count
            );
        return pr;
    }

EDIT
So the corrected code should read

//create the PageResult object
var pr = new PageResult<OrderVm>(
    results as IEnumerable<OrderVm>,
    request.GetNextPageLink(),
    request.GetInlineCount();
    );
return pr;

EDIT
Avoided the need for a string transformation of the enum in the controller method by applying a Json transformation to the OrderStatusId property (an enum) of the OrderVm class

[JsonConverter(typeof(StringEnumConverter))]
public OrderStatus OrderStatusId { get; set; }

This does away with the foreach loop.

Best Answer

InlineCount would be present only when the client asks for it through the $inlinecount query option.

In your modify uri logic add the query option $inlinecount=allpages if it is not already present.

Also, there is a minor bug in your code. The new ODataQueryOptions you are creating uses a new request where as in the GetInlineCount call, you are using the old Request. They are not the same.

It should be,

var count = request.GetInlineCount(); // use the new request that your created, as that is what you applied the query to.
Related Topic