Introduction
Implementing pagination and filtering using custom middleware can significantly optimize API responses and enable efficient handling of large datasets. Here's a step-by-step example of how to achieve this:
Step 1. Create a new ASP.NET Core Web API project using Visual Studio or the .NET CLI
Create an Asp.net core application using Visual Studio or the CLI commands
Step 2. Implement a custom middleware for pagination and filtering
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Threading.Tasks;
Author: Sardar mudassar ali khan
public class PaginationFilterMiddleware
{
private readonly RequestDelegate _next;
public PaginationFilterMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Query.ContainsKey("page") &&
context.Request.Query.ContainsKey("pageSize"))
{
if (int.TryParse(context.Request.Query["page"], out int page) &&
int.TryParse(context.Request.Query["pageSize"], out int pageSize))
{
var originalBodyStream = context.Response.Body;
using (var responseBody = new System.IO.MemoryStream())
{
context.Response.Body = responseBody;
await _next(context);
context.Response.Body.Seek(0, System.IO.SeekOrigin.Begin);
if (context.Response.StatusCode == 200) // Only apply pagination to successful responses
{
var response = await new System.IO.StreamReader(context.Response.Body).ReadToEndAsync();
var responseData = JsonConvert.DeserializeObject(response);
if (responseData is IEnumerable<object> data)
{
var totalItems = data.Count();
var totalPages = (int)Math.Ceiling((double)totalItems / pageSize);
var paginatedData = data.Skip((page - 1) * pageSize).Take(pageSize);
var paginationHeader = new
{
TotalItems = totalItems,
TotalPages = totalPages,
CurrentPage = page,
PageSize = pageSize
};
context.Response.Headers.Add("Pagination", JsonConvert.SerializeObject(paginationHeader));
var serializedData = JsonConvert.SerializeObject(paginatedData);
await context.Response.WriteAsync(serializedData);
}
}
context.Response.Body.Seek(0, System.IO.SeekOrigin.Begin);
await context.Response.Body.CopyToAsync(originalBodyStream);
}
}
}
else
{
await _next(context);
}
}
}
Step 3. Configure the custom middleware and implement pagination and filtering in the controller
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
Author: Sardar Mudassar Ali Khan
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Add pagination and filtering middleware
services.AddTransient<PaginationFilterMiddleware>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Use the custom pagination and filtering middleware
app.UseMiddleware<PaginationFilterMiddleware>();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Farrukh RehmanPosted Sep 8, 2023, 6:57 AM
//another alternative wayExpression<Func<Case, bool>> filter1 = entity => entity.IsActive == true; // Change as needed var result = await _serviceManager.Cases.GetFilteredAsync(filter1); int totalPages = (int)Math.Ceiling((double)result.Count() / filters.PageSize); var pagedData = result .Where(x => (string.IsNullOrEmpty(filters.ReportNo) || x.ReportNo.ToLower() == filters.ReportNo.ToLower()) ) .Skip((filters.Page - 1) * filters.PageSize) .Take(filters.PageSize) .ToList(); return Ok(new PagedResponse<List<Case>>(pagedData, filters.Page, filters.PageSize,result.Count(), totalPages)); public class PagedResponse<T> { public PagedResponse(T data, int currentPage, int pageSize,int totalItems,int totalPages) { Data = data; CurrentPage = currentPage; PageSize = pageSize; TotalItems = totalItems; TotalPages = totalPages; } public T Data { get; set; } public int CurrentPage { get; set; } public int PageSize { get; set; } public int TotalItems { get; set; } public int TotalPages { get; set; } }
JosephsPosted Sep 3, 2023, 8:01 AM
Any update?
JosephsPosted Aug 29, 2023, 3:14 AM
Can you share working code github.
JosephsPosted Aug 29, 2023, 3:10 AM
Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: DotnetCore_Middleware_Pagination.PaginationNewFilterMiddleware Lifetime: Transient ImplementationType: DotnetCore_Middleware_Pagination.PaginationNewFilterMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'DotnetCore_Middleware_Pagination.PaginationNewFilterMiddleware