FilterResult<T>
FilterResult<T> is the strongly-typed wrapper returned by every terminal filter extension — ToList<T>(Filter), ToListAsync<T>(Filter), and the dynamic variants. It contains the result page plus pagination metadata.
Properties
| Property | Type | Description |
|---|---|---|
PageNumber | int | Current page (0 when no pagination). |
PageSize | int | Page size (0 when no pagination). |
PageCount | int | Total pages. 1 when the query carried no Page — an unpaged result is one page of everything — and 0 when nothing matched. |
TotalCount | int | Total matching records. |
Data | List<T> | The result entities. |
QueryString | string? | Generated SQL (when getQueryString: true is passed to the extension). |
Policy | PolicyTrace? | What the policy layer did to this query. null unless the query went through ApplyPolicy. A guarded query sets it as DwPolicyOptions.IncludeTraceInResult decides: by default it is present under the convenience tier and null under the strict tier (since 3.1.0 — see breaking changes). The trace is always on PolicyQueryable<T>.LastTrace. |
Note
When the input
Filter has no Page, PageNumber and PageSize come back as 0 and the full result sits in Data. PageCount is 1 — the one page the whole result occupies — or 0 when nothing matched. With a Page, it is Ceiling(TotalCount / PageSize).Changed in 3.1.0
An unpaged
PageCount used to equal TotalCount: the calculation divided by a page size of 1 whenever none was sent, so a 5,000-row result reported 5,000 pages of one row each. A client that draws a pager straight from PageCount now gets one page instead of one per row. PageNumber and PageSize are unchanged — both still 0 when no page was sent.A guarded query may be paged for you
On a guarded query, a deployment that sets
DwCaps.DefaultPageSize gives a request with no Page page 1 at that size, capped at MaxPageSize, so PageNumber, PageSize and PageCount come back as for any paged request. It never replaces a page the caller sent. A context declaring a purpose with page caps of its own in DwCaps.Purposes takes each of the two caps that purpose sets from it instead (3.4.0).C# usage
FilterResult<Customer> result = await dbContext.Customers.ToListAsync(filter);
Console.WriteLine($"page {result.PageNumber} of {result.PageCount}");
Console.WriteLine($"{result.TotalCount} total matches");
foreach (var customer in result.Data)
{
Console.WriteLine($"- {customer.Name}");
}JSON response example
{
"pageNumber": 1,
"pageSize": 10,
"pageCount": 5,
"totalCount": 42,
"data": [
{ "id": 7, "name": "John Doe", "createdAt": "2025-09-14T12:31:00Z" },
{ "id": 8, "name": "Jane Roe", "createdAt": "2025-09-13T08:11:00Z" }
],
"queryString": null,
"policy": null
}See also
- Filter →
- ToListAsync<T>(Filter) →
- SegmentResult<T> → inherits this shape.