ETA on $inlinecount in WebApi OData

Topics: ASP.NET Web API
Nov 28, 2012 at 9:32 AM

Hey,

Looking through the change sets I've noticed there are some attempts to add inline count in to the WebApi OData support. I'm just wondering if anybody knows when/if this will be added to the release?

Thanks

Mat

Coordinator
Nov 28, 2012 at 11:34 PM

We are trying to get this done for the final release of the ASP.NET Fall 2012 Update early next year. Vote for this Issue Tracker item to show your support!:

http://aspnetwebstack.codeplex.com/workitem/330

Daniel Roth

Nov 29, 2012 at 8:55 AM

Thanks! Scanning your reply I read Fall next year. Which I'm glad its not

Coordinator
Nov 29, 2012 at 5:18 PM

Ah, sorry - I used the old name for the release. The release targeted for early next year is now called Microsoft ASP.NET and Web Tools 2012.2. The "2012.2" is meant to match the versioning of the Visual Studio 2012 updates.

Dec 14, 2012 at 11:43 AM

Is the inline count in the RC candidate?

Coordinator
Dec 14, 2012 at 4:38 PM

No, but it is now checked in and will be available in the RTM release. You can try it out now by grabbing a nightly build from MyGet.

http://aspnetwebstack.codeplex.com/wikipage?title=Use%20Nightly%20Builds

Daniel Roth

Dec 18, 2012 at 2:20 PM

I hate to ask, but can someone post an example how to use it. I have compiled the dll from source and have the new inline count stuff. However I can't seem to figure out how to use it.

When I use this code with $inlinecount=allpages in the query I get no inlinecount.

 

        [Queryable]
        public IQueryable<Resource> Get()
        {
            try
            {
                return entities.Resources;

            }
            catch (Exception ex)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

 

Going the more complex route:

 public ODataResult<Resource> Get(ODataQueryOptions options)
        {
            var results = (options.ApplyTo(entities.Resources) as IQueryable<Resource>);
            return new ODataResult<Resource>(results, new Uri("http://nextpage"), options.InlineCount.GetEntityCount(entities.Resources));
        }

This gives me an extra count value in the result, but only the items on the page. not allpages.

Can anyone point out the obvious for me?

 

 

Dec 18, 2012 at 5:14 PM

Hi,

$inlinecount would be present in the on-wire response only with the odata formatter. only odata protocol has a field for specifying $inlinecount in the response payload. The default json and xml formats don't have any. That said, if you want to output the count in the response for these formats you can get the value from the request property bag using,

Request.Properties["MS_InlineCount"]

You can then have a message handler to put this as a response header or in the response body or anywhere your client expects it to be.

And regarding your other question, $inlinecount=allpages doesn't return you all the pages. It just returns the count. http://msdn.microsoft.com/en-us/library/dd942040.aspx

Dec 18, 2012 at 6:51 PM

To reiterate what Raghuram is saying,

1) $inlinecount only works by default for the OData formatter.

2) If you want to have the $inlinecount work for a different formatter, you can either return an object from your action that contains the inline count or you can add support in the formatter to get the inline count and serialize it out. You can get the inline count to send back to the client by using the following method:

Request.GetInlineCount()
Dec 18, 2012 at 9:02 PM

Thank you for your responses,

I know allpages does not return all pages but the itemcount after filter but before an top and skip and such. English is not my native language and I stated that clumsily. It was correct of you to remind me of that.

I can't see why $inlinecount could only be added to the odata formatter. An ordinary json or xml response could surely be wrapped in an object with an inlinecount property. Most certainly when the action returns an odataresult. However i can accept that is not the way it is done by default. I will just create my own formatter to compensate for this.

 

Coordinator
Dec 18, 2012 at 9:06 PM

Why bother with your own formatter? Why not just use the OData formatter for you JSON and XML representation?

Dec 18, 2012 at 9:31 PM
danroth27 wrote:

Why bother with your own formatter? Why not just use the OData formatter for you JSON and XML representation?

  Apparently I'm missing something here. All these new webapi and odata things are very new to me. From the preview on, I liked it because i could dynamicaly query my entities with a very simple REST service and a filter statement, just by adding an [queryable] attribute or thru odatasetting/odataresult if I wanted more control. I read about top and skip for paging and was even happier. Then I read that inlinecount had been added to the source to make (for me) paging really usefull.

I know output can be changed to json or xml by specifying it in the request., but now you talk about an odataformatter that also outputs xml or json.

I'm confused, I expected that with inlinecount added I had something to put in the third parameter for odataresult. Can you enlighten me some more?

public ODataResult<Resource> Get(ODataQueryOptions options)
        {
            var results = (options.ApplyTo(entities.Resources) as IQueryable<Resource>);
            return new ODataResult<Resource>(results, new Uri("http://nextpage"), "what goes here? Request.GetInlineCount()?"

);
        }

Coordinator
Dec 18, 2012 at 11:57 PM

You are correct that we have done our best to keep the OData query support separate from the OData format support. This allows you to support OData style queries over any format including the ones produced by our default JSON and XML formatters.

However there are some OData features that rely on data in the request or response. $inlinecount is one of those features. How should a client find the $inlinecount in the response message? The OData spec provides a standardized way to find the $inlinecount that frameworks can then implement. You can of course roll your own format for specifying the $inlinecount in the response in your own way, but then it's up to you to teach your client applications how to find it.

Our default JSON and XML formatters leave a lot of questions unanswered for how certain data should be formatted (ex next links, self links, paging, inline count, etc). The OData formatter provides a standardized way for formatting these common patterns so you don't have to reinvent them, which hopefully saves you time. If you find it's still easier to roll your own format that's perfectly fine - it's just good feedback to us to make the OData scenarios even easier :-).

Daniel Roth

Dec 19, 2012 at 11:05 AM
Edited Dec 19, 2012 at 11:06 AM

 

I just had the time to try it out and using Request.getinlinecount() as the count parameter for an odataresult gives the result I want. the list of objects and an count of the total after filtering / skip/ top. Thank you all for helping.

Unfortunately with the source I checked out yesterday I get an exception when trying to use $filter. I do not know yet if it's my code or yours, but I thought I post it anyway, maybe someone recognizes it. It does not matter what I use as filtertext. (That's what you get for being on the bleeding edge)

 

<Error><Message>An error has occurred.</Message><ExceptionMessage>Method not found: 'Int32 Microsoft.Data.OData.Query.SemanticAst.QueryNode.get_Kind()'.</ExceptionMessage><ExceptionType>System.MissingMethodException</ExceptionType><StackTrace>   at System.Web.Http.OData.Query.Expressions.FilterBinder.Bind(QueryNode node)
   at System.Web.Http.OData.Query.Expressions.FilterBinder.BindFilterClause(FilterClause filterClause)
   at System.Web.Http.OData.Query.Expressions.FilterBinder.Bind(FilterClause filterClause, Type filterType, IEdmModel model, IAssembliesResolver assembliesResolver, ODataQuerySettings querySettings)
   at System.Web.Http.OData.Query.FilterQueryOption.ApplyTo(IQueryable query, ODataQuerySettings querySettings, IAssembliesResolver assembliesResolver)
   at System.Web.Http.OData.Query.ODataQueryOptions.ApplyTo(IQueryable query, ODataQuerySettings querySettings)
   at System.Web.Http.OData.Query.ODataQueryOptions`1.ApplyTo(IQueryable query, ODataQuerySettings querySettings)
   at System.Web.Http.OData.Query.ODataQueryOptions.ApplyTo(IQueryable query)
   at System.Web.Http.OData.Query.ODataQueryOptions`1.ApplyTo(IQueryable query)
   at EduConLibrary.Services.Controllers.ResourcesController.Get(ODataQueryOptions options) in c:\Users\bzs.ROCWBLOCAL\Documents\Visual Studio 2012\Projects\EduConWeb\EduConLibrary\Services\ResourcesController.cs:line 41
   at lambda_method(Closure , Object , Object[] )
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters)
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4()
   at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)</StackTrace></Error>
Dec 19, 2012 at 5:43 PM

Sorry about this. There is a codeplex workitem tracking this http://aspnetwebstack.codeplex.com/workitem/721

From the workitem update,

"we found out this issue as well :(. ODataLib(our dependency) has published a new version (5.2.0 RTM) of their package which has some breaking changes. Unfortunately, nuget downloads the latest version of that package due to the way we had our dependencies mentioned.

Please manually uninstall the 5.2.0 version of ODataLib and install 5.2.0-rc1. That should solve this."

Dec 20, 2012 at 8:49 AM

Thank you for the information! There is not need to apologize, that why it's called an development version.

Dec 20, 2012 at 4:12 PM

I saw this same issue (or at least this same exception dealing with filters). Odd thing is that when I get the source and use that instead of the nuget package of the latest dev binaries, I don't get that exception. And I am using the 5.2.0 nuget package of Microsoft.Data.OData.

Dec 21, 2012 at 9:48 AM
richardgavel wrote:

I saw this same issue (or at least this same exception dealing with filters). Odd thing is that when I get the source and use that instead of the nuget package of the latest dev binaries, I don't get that exception. And I am using the 5.2.0 nuget package of Microsoft.Data.OData.

I can also confirm this. The latest nighly still has a dependency problem. But when checking out the source code from codeplex and updating ODataLib from the 5.2.0-rc1 to 5.2.0 that build of the code works fine with filter. Hope the upgrade the codeplex version soon.