Repository navigation
Getting Started
This page walks you from dotnet add package to a working paged endpoint in a few minutes. The shortest path is the EF Core extensions; the optional second half wires the same flow into ASP.NET Core (controllers and minimal APIs).
For most projects you only need the top-level package, which transitively brings in the data models and the expression builders:
Install-Package RzR.ResultMessage.Pagination.Abstractions
Install-Package RzR.ResultMessage.Pagination.Core
Install-Package RzR.ResultMessage.Pagination.EntityFrameworkCore
Install-Package RzR.ResultMessage.Pagination.AspNetCoreIf you also want the ASP.NET Core integration (controllers, model binders, minimal-API helpers, headers, OpenAPI conventions), add the Web integration package as well. Its assembly is RzR.ResultMessage.Pagination.AspNetCore and it requires the matching framework target.
| You only need... | Install |
|---|---|
| The DTO contract shared with a client | RzR.ResultMessage.Pagination.Abstractions |
The IQueryable<T> extensions on top of EF Core |
RzR.ResultMessage.Pagination.EntityFrameworkCore |
| Everything plus the ASP.NET Core glue |
RzR.ResultMessage.Pagination.EntityFrameworkCore and RzR.ResultMessage.Pagination.AspNetCore
|
Open a using directive on RzR.ResultMessage.Pagination.EntityFrameworkCore and call GetPagedAsync on any IQueryable<T>:
using RzR.ResultMessage.Pagination.EntityFrameworkCore;
using RzR.ResultMessage.Pagination.Abstractions.Models.Result;
PagedResult<Product> page = await _db.Products
.OrderBy(p => p.Id)
.GetPagedAsync(page: 1, pageSize: 25, cancellationToken);
// page.Response -> IList<Product>
// page.RowCount -> total filtered rows
// page.PageCount -> total pages
// page.CurrentPage -> 1
// page.PageSize -> 25
// page.HasNextPage -> derived
// page.HasPreviousPage-> derived
// page.ExecutionDetails.ExecutionTimeMsThat is the minimum surface of the library. Everything else builds on top of this primitive.
The same call signature accepts a PagedRequest (or its PageRequestWithFilters subclass) coming straight from the API consumer. With this overload you also get search, ordering, projection and predefined-records handling, all driven by the request body:
public async Task<PagedResult<Product>> GetProducts(
PagedRequest request, CancellationToken ct)
{
var query = _db.Products.AsNoTracking();
return await query.GetPagedAsync(request, cancellationToken: ct);
}If the request type extends PageRequestWithFilters, switch to one of the filter-aware overloads:
return await query.GetPagedWithFiltersAsync(
request,
new DefaultPrimaryKeyDefinition("Id"), // optional, only needed for predefined records
filterLink: FilterConditionType.And,
cancellationToken: ct);For the field-by-field semantics of PagedRequest, see Data Models Reference. For the difference between the three filter variants, see EntityFramework Core Extensions.
Inherit from BaseApiPagedResultController to get the success and failure helpers:
using Microsoft.AspNetCore.Mvc;
using RzR.ResultMessage.Pagination.AspNetCore;
using RzR.ResultMessage.Pagination.Abstractions.Abstractions;
[Produces("application/json")]
[Route("api/[controller]/[action]")]
public sealed class ProductsController : BaseApiPagedResultController
{
private readonly AppDbContext _db;
public ProductsController(AppDbContext db) => _db = db;
[HttpPost]
public async Task<IActionResult> List(
[FromBody] PageRequestWithFilters request, CancellationToken ct)
{
IPagedResult<Product> result = await _db.Products
.AsNoTracking()
.GetPagedWithFiltersAsync(request, cancellationToken: ct);
return PagedOkResult(result);
}
}PagedOkResult returns 200 OK with the full envelope on success and an RFC 9457 application/problem+json body on failure. See MVC Integration for the [FromPagedQuery] query-string variant and the obsolete-helper notes.
In Program.cs register the integration once:
builder.Services
.AddControllers()
.AddPagedListResultApiExplorer(); // OpenAPI auto-annotations
builder.Services
.AddPagedListResultWeb(o =>
{
o.MaxPageSize = 100;
o.DefaultPageSize = 25;
});That single call wires the model binder, the response-header filter, the per-type metadata registry and the MvcOptions convention. See Configuration and Options for the complete option reference.
The minimal-API surface mirrors the MVC pipeline through dedicated bindable wrappers. PagedQuery<T> and PagedQueryWithFilters<T> live in RzR.ResultMessage.Pagination.AspNetCore.Query (renamed from ...MinimalApi in v5) and, as of v5, also bind in MVC when used as [FromPagedQuery] action parameters — see MVC Integration.
app.MapGet("/products",
async (PagedQueryWithFilters<Product> q, AppDbContext db, HttpContext ctx, CancellationToken ct) =>
{
if (!q.IsValid)
return Results.ValidationProblem(
q.Errors.ToDictionary(e => e.Key, e => new[] { e.Value }));
var paged = await db.Products
.AsNoTracking()
.GetPagedWithFiltersAsync(q, cancellationToken: ct);
return paged.ToPagedHttpResult(ctx);
})
.WithPagedResult();WithPagedResult() attaches the endpoint filter that emits the standard pagination headers, and ToPagedHttpResult makes sure the full paged envelope (paging metadata included) is serialized on success while still routing failures through the upstream ProblemDetails machinery. Details in Minimal API Integration.
Once your endpoint is up, the supported request shapes are:
-
Body-bound JSON (any of the request models). See Data Models Reference.
-
Query string. See Query String Syntax for the full grammar:
GET /products ?page=2 &pageSize=20 &order=price:desc &search=usb &filter=status:Equals:active &filter=price:Between:10,100
The response always carries the PagedResult<T> envelope (paging metadata + Response items + execution details + result messages). On failure, the body is an RFC 9457 ProblemDetails document.
- Curious about the request shape? See Data Models Reference.
- Need to lock down which properties may be sorted or filtered by clients? See Allow List Registry.
- Coming from v2.x and hitting compile errors? See Migration Guide.
PagedListResult is maintained by RzR. GitHub repository.
Start here
Reference
- Data Models Reference
- Expression Builders (Common)
- EntityFramework Core Extensions
- Query String Syntax
ASP.NET Core integration
- Web Integration Overview
- MVC Integration
- Minimal API Integration
- Configuration and Options
- Allow List Registry
- Response Headers and ProblemDetails
- OpenAPI and ApiExplorer
Operations