Repository navigation
Web Integration Overview
PagedListResult.Web (assembly RzR.ResultMessage.Pagination.AspNetCore) connects the EF Core extensions to ASP.NET Core. It is the single package you add when you want a paged endpoint to "just work": query-string parsing, model binding, success and failure shaping, response headers, OpenAPI annotations, and an opt-in allow-list of sortable / filterable / searchable properties.
This page is the high-level map of the integration. Each component links to its own page for the detailed reference.
| Component | Type | When it is used |
|---|---|---|
AddPagedListResultWeb(...) |
DI registration | Once in Program.cs. |
AddPagedListResultApiExplorer() |
IMvcBuilder extension |
Once in Program.cs, registers the OpenAPI convention. |
BaseApiPagedResultController |
Base controller class | Inherit from it instead of ControllerBase. |
PagedOkResult<T> / PagedXmlResult<T>
|
Action result helpers | Return them from controller actions. |
[FromPagedQuery] |
Action-parameter attribute | Signal that a PagedRequest should be bound from the query string. |
PagedQuery<T> / PagedQueryWithFilters<T>
|
Dual-host query wrappers | Accept them directly in a Minimal API endpoint delegate, or as [FromPagedQuery] MVC action parameters (.NET 7+). Namespace RzR.ResultMessage.Pagination.AspNetCore.Query. |
WithPagedResult() |
IEndpointConventionBuilder extension |
Register the endpoint filter that emits headers (.NET 7+). |
ToPagedHttpResult(...) |
IPagedResult<T> extension |
Build the minimal-API IResult that preserves the envelope on success and routes failures through ProblemDetails (.NET 7+). |
PagedListResultBuilder.ConfigurePageable<T>(...) |
Fluent registration | Restrict which properties may be sorted/filtered/searched per entity type. |
HTTP request
|
v
Model binder (MVC) or PagedQuery<T>.BindAsync (minimal API)
|
|-- parses query string via PagedRequestQueryParser
|-- consults the allow-list (PageableMetadataRegistry)
|-- writes ModelState errors per malformed filter row
v
Controller action / endpoint delegate
|
|-- runs your business logic, calls GetPaged* on EF Core
v
Action filter (MVC) or endpoint filter (minimal API)
|
|-- unwraps the action/endpoint result Value
|-- if the value implements IPagedResult, calls PagedResponseHeaderWriter
|-- writes X-Total-Count / X-Page-Count / X-Page-Size / X-Current-Page
|-- writes Link header (RFC 5988) only for GET requests when PageCount > 0
|-- writes Server-Timing: paged;dur=<ms> if EmitServerTimingHeader is true
v
Response shaper
|
|-- MVC: PagedOkResult / PagedXmlResult
|-- Minimal API: ToPagedHttpResult
v
HTTP response
|
|-- 200 OK with the full envelope on success
|-- 204 No Content if the paged result reference is null
|-- application/problem+json (RFC 9457) on failure
-
AddPagedListResultWeb(Action<PagedListResultWebOptions>?)registers the options, the singletonPageableMetadataRegistry(only if the consumer did not already supply one), and amendsMvcOptionsto insert the model binder provider at index 0, the application-model convention, and aServiceFilterAttribute(typeof(PagedResultActionFilter)). -
AddPagedListResultApiExplorer()is a thinIMvcBuilderextension that addsPagedResultApplicationModelConventionif it is not already present. -
WithPagedResult()/AddPagedResultEndpointFilter<TBuilder>()(.NET 7+) attachPagedResultEndpointFilterto a route group or endpoint.
See Configuration and Options for the full options reference.
-
[FromPagedQuery]opts aPagedRequest-derived parameter into query-string binding. -
PagedRequestModelBinderProviderreturns the binder only when the attribute is present and the model type is assignable fromPagedRequest. -
PagedRequestModelBinderresolves the per-typePageableMetadataallow-list and delegates toPagedRequestQueryParser.Populate.
See MVC Integration and Query String Syntax.
-
PagedQuery<TEntity>andPagedQueryWithFilters<TEntity>(namespaceRzR.ResultMessage.Pagination.AspNetCore.Query, renamed from...MinimalApiin v5) are dual-host bindable wrappers. In Minimal API they self-bind viaBindAsync(HttpContext); in MVC they bind when used as[FromPagedQuery]action parameters. Both implement the sharedIPagedQueryValidationabstraction, which exposesIsValid/Errorsconsistently in either host. - Internally, the Minimal-API path uses
MinimalApiQueryBinder(aninternalimplementation detail, the counterpart of the MVCPagedRequestModelBinder) — it is not part of the public surface.
See Minimal API Integration and MVC Integration.
- MVC:
BaseApiPagedResultControllerexposesPagedOkResult<T>(IPagedResult<T>)(returns200 OKJSON orapplication/problem+json) andPagedXmlResult<T>(IPagedResult<T>)(returns SOAP/XML or ProblemDetails). OlderJsonResult<T>/XmlResult<T>helpers are kept as[Obsolete]shims for one release. - Minimal API:
ToPagedHttpResult(this IPagedResult<T>, HttpContext?)builds aMicrosoft.AspNetCore.Http.IResultthat preserves the full envelope on success. -
PagedResultActionFilter(MVC) andPagedResultEndpointFilter(minimal API) write the response headers without changing the body.
See Response Headers and ProblemDetails.
-
PagedResultApplicationModelConventionwalks every controller action that returns anIPagedResult<T>(or wraps one inTask<>,ValueTask<>,ActionResult<>) and attachesProduces("application/json"),ProducesResponseType(typeof(PagedResult<T>), 200)andProducesResponseType(typeof(ProblemDetails), 400)if the user has not supplied them. -
PageableMetadataRegistry(defaultIPageableMetadataRegistryimplementation) maintains aConcurrentDictionary<Type, PageableMetadata>of allow-listed properties per entity type. Populated throughPagedListResultBuilder.ConfigurePageable<T>(...)during registration.
See OpenAPI and ApiExplorer and Allow List Registry.
Most consumers only need three things:
// Program.cs
builder.Services
.AddControllers()
.AddPagedListResultApiExplorer();
builder.Services
.AddPagedListResultWeb(o =>
{
o.MaxPageSize = 100;
})
.ConfigurePageable<Product>(p =>
{
p.AllowSort("Id", "Name", "Price", "CreatedOn");
p.AllowFilter("Status", "Price", "CreatedOn");
p.AllowSearch("Name", "Description");
});// Controller
public sealed class ProductsController : BaseApiPagedResultController
{
[HttpPost]
public async Task<IActionResult> List(
[FromBody] PageRequestWithFilters request, CancellationToken ct) =>
PagedOkResult(await _db.Products.AsNoTracking()
.GetPagedWithFiltersAsync(request, cancellationToken: ct));
[HttpGet]
public async Task<IActionResult> List(
[FromPagedQuery(typeof(Product))] PageRequestWithFilters request, CancellationToken ct) =>
PagedOkResult(await _db.Products.AsNoTracking()
.GetPagedWithFiltersAsync(request, cancellationToken: ct));
}That is enough to get the JSON envelope, the ProblemDetails error path, the standard headers and the OpenAPI annotations. The rest of the pages in this section explain how to customize each piece.
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