Skip to main content

WCF Pagination

In many of my projects  including last one I need to user N-Tier architecture for my application. This is very good approach because you can centralize your business logic and have many type of clients (WWW, mobile devices) thanks WCF and REST technology. The other thing is that most of business solutions displays some data in tabular format knows as grids and grid has always one problem: number of records increasing in time. So we need to ask ourselves do we really need to display all the data together  to user on one page? Of course not! Such approach is incorrect and not against best practices because its extends the time of response and send a much more data to client. To deal with that problem many developers uses pagination mechanism which is part of ASP.NET (ex. asp:Grid) but such approach is not correct when working with N-Tier architecture and its not supported in any mobile devices.

In my approach I wish to implement all my business logic and services by using Service Factory design pattern for WCF. Because I going to focus only at the pagination mechanism there is no need to add additional classes for accessing an database that is why I going to use mocking to create some data except.

At the beginning take a look at solution high level architecture (picture 1.). The solution contains two separated solution folder. Tests folders contains only one console application project for web service testing purposes. Folder WCF contains following projects:

  • Common: dll with implementation of public interfaces and classes shared across whole solution.
  • Contracts: dll  with definitions for classes uses as parameters for services methods. According best practices all service methods take 0 or only one parameter(which always derive from BaseRequest class) and returns type of response (which always derive from BaseResponse class).
  • DataTransferObjects: dll with types uses in communication in requests and responses. These types implements interfaces from namespaces Common.DTO and database entities also should implements its.
  • Namespaces: dll with constans namespaces for services, services contracts, service interfaces and so on.
  • ServiceImplementation: dll, core library with implementation of business logic for WCF services where classes implements service contracts.
  • ServiceInterfaces: dll, services contracts.
  • Services: WCF application, stores .svc files and configuration file (Web.config)


Picture 1. solution high level architecture.
Now when we know all solution we can focus on details of pagination. For presentation purpose I created one service called UserService with only one method GetUsers. This method returns list of users which will be paginated according to request parameters.

Code Snippet
  1. [ServiceContract(Namespace = ConstNamespaces.ServiceRoot, SessionMode = SessionMode.Allowed)]
  2.     public interface IUserService
  3.     {
  4.         [OperationContract]
  5.         GetUsersResponse GetUsers(GetUsersRequest request);
  6.     }

To enable pagination for list some additional implementation had to be introduced (picture 2.). The most important class for that is generic ListRequest<T> which implements a generic interface IRaginationRequest<T>. Those interface has only two int null-able properties which determine number of page to display and number of result per page - by default pagination return first page with maximum 20 results. Because we I use here genetic types in GetUserRequest declaration I simply can  declare type of T as User type which is my DTO  object.

Picture 2. Structure of a pagination request.


Picture 3. Structure for a pagination response.

Now  its time to implement service logic for returning paginated list of users. As I mentioned before in this post, I using mocking except of database that is why I create 100 users in  for loop with some test properties. After filling the list it`s time for apply pagination mechanism on it. For pagination I`ve created extension generic method called AsPagination  which extend IEnumerable interface of T type and takes one generic parameter of type IPaginationRequest. This  is quite obvious because in the request (which implements that interface) we pass all required data for pagination. Because pagination function returns value of generic type IPagination and there is no possibility to pass interface by WCF it need to be converted to class type and this explains GetUserResponse structure (Picture 3.).

Code Snippet
  1. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  2.   [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
  3.   public class UserService : IUserService
  4.   {
  5.       public GetUsersResponse GetUsers(GetUsersRequest request)
  6.       {
  7.           List<User> users = new List<User>();
  8.  
  9.           //Mocking response from DB.
  10.           for (int i = 0; i < 100; i++)
  11.               users.Add(new User()
  12.               {
  13.                   Id = Guid.NewGuid(),
  14.                   Email = string.Format("test{0}.test.com", i),
  15.                   FirstName = string.Format("Name_For_User_{0}", i),
  16.                   LastName = string.Format("Last_Name_For_User_{0}", i),
  17.               });
  18.  
  19.           var result = users.AsPagination<User>(request);
  20.           return new GetUsersResponse() { ResultList = new Pagination<User>(result) };
  21.       }
  22.   }

To  fully understand pagination mechanism you must be familiar with IQueryable interface and deferred execution on queries because both are used in the implementation. Pagination mechanism is optimized which means that you get only records which you really requested. For example, if you want to see 10 record on 5th page you need get from database only 10 records. You can achieve this by using Skip and Take LINQ  functions and know page size and number.If know both value of these variables you can simply use following LINQ query:

Code Snippet
  1. Query.Skip(numberToSkip).Take(PageSize);



Picture 4. Pagination mechanism overview.
At this stage there is no sorting and ordering in pagination list because it will be introduced in further post. 

Full projects source code is free available here.

Thank you.

Read more:







Popular posts from this blog

Full-Text Search with PDF in Microsoft SQL Server

Last week I get interesting task to develop. The task was to search input text in PDF file stored in database as FileStream. The task implementation took me some time so I decided to share it with other developers. Here we are going to use SQL Server 2008 R2 (x64 Developers Edition), external driver from Adobe, Full-Text Search technology and FileStream technology.Because this sems a little bit comlicated let`s make this topic clear and do it step by step. 1) Enable FileStream - this part is pretty easy, just check wheter You already have enabled filestream on Your SQL Server instance - if no simply enable it as in the picture below. Picture 1. Enable filestream in SQL Server instance. 2) Create SQL table to store files  - mainly ther will be PDF file stored but some others is also be allright. Out table DocumentFile will be created in dbo schema and contain one column primary key with default value as sequential GUID. Important this is out table contains FileSt...

Persisting Enum in database with Entity Framework

Problem statement We all want to write clean code and follow best coding practices. This all engineers 'North Star' goal which in many cases can not be easily achievable because of many potential difficulties with converting our ideas/good practices into working solutions.  One of an example I recently came across was about using ASP.NET Core and Entity Framework 5 to store Enum values in a relational database (like Azure SQL). Why is this a problem you might ask... and my answer here is that you want to work with Enum types in your code but persist an integer in your databases. You can think about in that way. Why we use data types at all when everything could be just a string which is getting converted into a desirable type when needed. This 'all-string' approach is of course a huge anti-pattern and a bad practice for many reasons with few being: degraded performance, increased storage space, increased code duplication.  Pre-requirements 1. Status enum type definition...

Using Newtonsoft serializer in CosmosDB client

Problem In some scenarios engineers might want to use a custom JSON serializer for documents stored in CosmosDB.  Solution In CosmosDBV3 .NET Core API, when creating an instance of  CosmosClient one of optional setting in  CosmosClientOptions is to specify an instance of a Serializer . This serializer must be JSON based and be of  CosmosSerializer type. This means that if a custom serializer is needed this should inherit from CosmosSerializer abstract class and override its two methods for serializing and deserializing of an object. The challenge is that both methods from  CosmosSerializer are stream based and therefore might be not as easy to implement as engineers used to assume - still not super complex.  For demonstration purpose as or my custom serializer I'm going to use Netwonsoft.JSON library. Firstly a new type is needed and this must inherit from  CosmosSerializer.  using  Microsoft.Azure.Cosmos; using  Newtonsoft.Json; usin...