Server Driven Paging With WCF Data Services

  • Download Sample Application
  • Server Side
    1. What is SDP ?
    2. Design notes Blog post , Channel 9 video
    3. Enabling SDP on the server.
    4. Setting Server-side paging limits in InitializeService.
    5. How to detect if a set is paged from the server-side.
    6. How QueryInterceptors affect the next link Uri.
    7. Navigating the next link Uri in the browser
  • Client Side
    1. SDP and DataServiceCollection APIs
    2. SDP and QueryOperationResponse

Server Side

3. Enabling SDP on the server.

On the Server-side , to use any of the V2 features , the DataServiceBehavior has to be set to V2.
config.DataServiceBehavior.MaxDataServiceProtocolVersion = DataServiceProtocolVersion.V2;

4. Setting Server-side paging limits in InitializeService.

To have the SDP limits applied to an entity set on the server-side , you need to configure the
page size on that entity set by using the SetEntitySetPageSize API available on DataServiceConfiguration.

int requestSizeLimit = 5;
config.SetEntitySetPageSize("*", requestSizeLimit);

5. How to detect if a set is paged on the server-side

From the metadata, no way.
We don’t expose any information in the $metadata endpoint that a particular set is paged on the server-side.
Without browsing to each entity set exposed by the service and asking for all the entities , there is no way to detect that a set is server paged.
The client developer has to know that the paging limits are set on the server-side to change the client code accordingly.
For more information about client side Querying strategies , please see the section :

6. How QueryInterceptors affect server side paging.

Applying a QueryInterceptor to an entity set would cause the total visible amount of data to the Data Service to be filtered.
If the Server can’t see it , it can’t page it. In other words, any limits that are currently in place now and apply to the /EntitySet
endpoint , will continue to hold after enabling Server Driven paging for that Entity Set.

Client Side

1. SDP and DataServiceCollection APIs

With the introduction of the SDP and DataBinding support in the client library , we have a new collection type called DataServiceCollection which provides support for natively reading the NextLinkUri , if it‘s present in the ATOM returned from the server. The type contains a property called Continuation,which contains the nextLinkUri present in the payload.

DataServiceCollection<T>.Continuation Property on MSDN 
The simplest example of using this collection type is to use the DataServiceCollection type to hold the results of a Query.
The attached sample application contains more scenario based examples.

   //Create an empty DataServiceCollection to hold the results of a query
  DataServiceCollection<Customer> customersPagedCollection = new DataServiceCollection<Customer>();
  var customersQuery = (from c in ServiceContext.Customers
                                  where c.Name.StartsWith("P")
                                  select c) as DataServiceQuery<Customer>;
  //Execute the query asynchronously
  customersQuery.BeginExecute(
    (asyncResult) =>
     {
       var customerQueryResponse = customersQuery.EndExecute(asyncResult) as QueryOperationResponse<Customer>;
       //Call load on the DataServiceCollection with the QueryOperationResponse
       //This will cause the collection to load the customer objects 
       //and the nextlink as found in the response.
       customersPagedCollection.Load( customerQueryResponse );
     }, null
  );

Seeing as it is that the above pattern of querying for top level collections is a common practice in Silverlight applications,

we’ve introduced a method on the DataServiceCollection type to make this easier.

Behold, the LoadAsync method on DataServiceCollection<T> for materializing top level collections without any user code.

And the LoadNextPartialSetAsync method to load the next page in the collection.

To load the next page in the Collection, call the Execute<T>,BeginExecute<T> overloads which take a continuation token.

 //To Load the next page, call the Execute<T> overload which takes a continuation token
 ServiceContext.BeginExecute(customersPagedCollection.Continuation, QueryCallback, null);

Call the LoadNextPartialSetAsync method in your Silverlight applications:

 customersPagedCollection.LoadNextPartialSetAsync();

2. SDP and QueryOperationResponse

In case you don’t want to use the DataServiceCollection<T> type and instead want to use your own collection type,

then fear not . You don’t have to use the DataServiceCollection type if you want to have Paging Support in the client library. The QueryOperationResponse<T> type from V1 has been updated to support Paging using custom collections. 
The type now contains a new method called GetContinuation which will give you the continuation token if one was present in the response.

QueryOperationResponse<T>.GetContinuation Method  on MSDN

Consider a custom collection type called MyCollection and looks like this :

 /// <summary>
/// Custom collection type to illustrate pluggability of Continuation token.
/// </summary>
/// <typeparam name="TEntity">The Entitytype of the collection</typeparam>
public class MyCollectionType<TEntity> : List<TEntity> where TEntity : class, new() {
    /// <summary>
    /// This is a custom property on a collection type which can hold the continuation token
    /// Call GetContinuation on the response to get the continuation token for the response
    /// </summary>
    public DataServiceQueryContinuation<TEntity> NextLink { get; set; }
}

Here’s an example of getting the continuation token and using it in the collection type:

    //Create the custom collection type and add the results of the query to the collection
   MyCollectionType<Customer> customCustomersCollection = new MyCollectionType<Customer>();
   var customersQuery = (from c in ServiceContext.Customers
                                  where c.Name.StartsWith("P")
                                  select c) as DataServiceQuery<Customer>;
   //Execute the query asynchronously
   customersQuery.BeginExecute(
       (asyncResult) =>
        {
          var customerQueryResponse = customersQuery.EndExecute(asyncResult) as QueryOperationResponse<Customer>;
          foreach (Customer customerInstance in customerQueryResponse)
           {
             customCustomersCollection.Add(customerInstance);
           }
         //Calling GetContinuation without any parameters gives you the nextlink of the 
         //top level feed element in the response
         customCustomersCollection.NextLink = customerQueryResponse.GetContinuation();
         }, null
     );

To load the next page in the Collection, call the Execute<T>,BeginExecute<T> overloads which take a continuation token.

 //To Load the next page, call the Execute<T> overload which takes a continuation token
 ServiceContext.BeginExecute(customCustomersCollection.NextLink , QueryCallback, null);

Comments

  • Anonymous
    October 07, 2010
    Thanks for the post. I would add that when configuring the service, to change the protocol version, it's first necessary to change the config parameter type from IDataServiceConfiguration interface to DataServiceConfiguration class, as explained here: <a href="blogs.msdn.com/.../a> The interface does not have DataServiceBehavior property.

  • Anonymous
    February 24, 2011
    Hi Phani, I am building a WPF app and want to load just the current page because i have thousands of records and i show only 100 records at a time. I clear the observable collection before loading it with fresh data. Is there a way to navigate back to previous server side page?