ReflectionIT.Mvc.Paging
11.0.0
Prefix Reserved
dotnet add package ReflectionIT.Mvc.Paging --version 11.0.0
NuGet\Install-Package ReflectionIT.Mvc.Paging -Version 11.0.0
<PackageReference Include="ReflectionIT.Mvc.Paging" Version="11.0.0" />
<PackageVersion Include="ReflectionIT.Mvc.Paging" Version="11.0.0" />
<PackageReference Include="ReflectionIT.Mvc.Paging" />
paket add ReflectionIT.Mvc.Paging --version 11.0.0
#r "nuget: ReflectionIT.Mvc.Paging, 11.0.0"
#:package ReflectionIT.Mvc.Paging@11.0.0
#addin nuget:?package=ReflectionIT.Mvc.Paging&version=11.0.0
#tool nuget:?package=ReflectionIT.Mvc.Paging&version=11.0.0
ReflectionIT.Mvc.Paging
ASP.NET Core library for paging and sorting (and filtering) of Entity Framework Core and IEnumerable<T> data sources, with a ready-to-use pager view component.
- Targets .NET 10.0 and .NET 11.0
- Async paging for
IQueryable<T>(EF Core) and sync paging forIEnumerable<T> - Multi-column and nested-property sorting, e.g.
"Name,-Age"or"Supplier.CompanyName" - Pager view component with Bootstrap 3, 4 and 5 views
- Sortable column headers that show a sort-direction indicator
- Page index is clamped automatically when it is out of range
Installation
dotnet add package ReflectionIT.Mvc.Paging
Quick start
1. Register (optional)
builder.Services.AddPaging(options => {
options.ViewName = "Bootstrap5"; // Bootstrap3 | Bootstrap4 | Bootstrap5
options.PageParameterName = "pageindex"; // default: "pageIndex"
options.SortExpressionParameterName = "sort"; // default: "sortExpression"
options.DefaultNumberOfPagesToShow = 7; // default: 5
});
2. _ViewImports.cshtml
@using ReflectionIT.Mvc.Paging
@addTagHelper *, ReflectionIT.Mvc.Paging
3. Controller
public async Task<IActionResult> Index(string filter, int pageindex = 1, string sort = "ProductName") {
var qry = _context.Products.AsNoTracking().AsQueryable();
if (!string.IsNullOrWhiteSpace(filter)) {
qry = qry.Where(p => EF.Functions.Like(p.ProductName, "%" + filter + "%"));
}
// pageSize = 10, default sort = "ProductName"
var model = await PagingList.CreateAsync(qry, 10, pageindex, sort, "ProductName");
// route values that are preserved in the pager and sort links
model.RouteValue = new RouteValueDictionary { { "filter", filter } };
return View(model);
}
4. View
@model PagingList<Product>
<nav aria-label="Products navigation">
<vc:pager paging-list="Model" />
</nav>
<table class="table">
<tr>
<th>@Html.SortableHeaderFor(m => m.ProductName)</th>
<th>@Html.SortableHeaderFor(m => m.Supplier.CompanyName, "Supplier.CompanyName, ProductName")</th>
<th>@Html.SortableHeaderFor(m => m.UnitPrice, htmlAttributes: new { @class = "text-end" })</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>@item.ProductName</td>
<td>@item.Supplier.CompanyName</td>
<td>@item.UnitPrice</td>
</tr>
}
</table>
Clicking a sortable header sorts ascending. Clicking it again toggles to descending (a - prefix), and so on.
Creating a PagingList<T>
All factory methods are on the static PagingList class and require pageSize > 0.
| Method | Use when |
|---|---|
CreateAsync(IOrderedQueryable<T>, pageSize, pageIndex) |
EF Core query that is already ordered |
CreateAsync(IQueryable<T>, pageSize, pageIndex, sortExpression, defaultSortExpression) |
EF Core query, sorted by a sort expression |
Create(IEnumerable<T>, pageSize, pageIndex) |
In-memory sequence, no sorting |
Create(IEnumerable<T>, pageSize, pageIndex, sortExpression, defaultSortExpression) |
In-memory sequence, sorted by a sort expression |
Create(IEnumerable<T>, pageSize, pageIndex, totalRecordCount, sortExpression, defaultSortExpression) |
You already paged and sorted the data and know the total count |
T must be a reference type. If pageIndex is below 1 it becomes 1. If it is above the page count it becomes the last page. An empty source returns page 1 with 0 pages.
Sort expressions
"Name": ascending"-Name": descending"Name,-Age": multiple columns"Supplier.CompanyName": nested property (IQueryable overload)
An unknown property throws an ArgumentException. When SortExpression equals DefaultSortExpression, the sort parameter is left out of the generated links.
PagingList<T> members
PagingList<T> derives from List<T> and holds the items of the current page.
| Member | Description |
|---|---|
PageIndex, PageCount, TotalRecordCount |
Paging metadata (PageIndex is 1-based) |
SortExpression, DefaultSortExpression |
Current and default sort |
Action |
Action used for links (default "Index") |
PageParameterName, SortExpressionParameterName |
Query parameter names |
RouteValue |
Extra route values included in every link (e.g. a filter) |
NumberOfPagesToShow, StartPageIndex, StopPageIndex |
Window of page links shown in the pager |
GetRouteValueForPage(int) / GetRouteDataForPage(int) |
Route values for a page link |
GetRouteValueForSort(string) |
Route values for a sort link (toggles direction) |
Pager view components
<vc:pager paging-list="Model" />
<vc:pager-with-named-view paging-list="Model" view-name="Bootstrap4" />
pager uses PagingOptions.Current.ViewName. pager-with-named-view takes an optional view name and falls back to the same default. You can supply your own pager view by adding a view with that name under Views/Shared/Components/Pager/. The model is IPagingList.
Options
PagingOptions.Current holds the global defaults:
| Option | Default |
|---|---|
ViewName |
"Bootstrap5" |
PageParameterName |
"pageIndex" |
SortExpressionParameterName |
"sortExpression" |
DefaultNumberOfPagesToShow |
5 |
HtmlIndicatorUp / HtmlIndicatorDown |
Bootstrap 3 glyphicon chevrons |
The sort indicators default to Bootstrap 3 glyphicons. Override them if you use another icon set:
options.HtmlIndicatorUp = " <i class=\"bi bi-chevron-up\"></i>";
options.HtmlIndicatorDown = " <i class=\"bi bi-chevron-down\"></i>";
Sample
See the SampleApp project, in particular ProductsController and Views/Products/Index.cshtml, for a complete example with filtering, sorting and paging.
Links
- Source: https://github.com/sonnemaf/ReflectionIT.Mvc.Paging
- Author: Fons Sonnemans, Reflection IT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. net11.0 is compatible. |
-
net10.0
- Microsoft.AspNetCore.Components (>= 10.0.15)
- Microsoft.AspNetCore.Components.Web (>= 10.0.15)
- Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation (>= 10.0.15)
- Microsoft.EntityFrameworkCore (>= 10.0.15)
-
net11.0
- Microsoft.AspNetCore.Components (>= 11.0.0)
- Microsoft.AspNetCore.Components.Web (>= 11.0.0)
- Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation (>= 11.0.0)
- Microsoft.EntityFrameworkCore (>= 11.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 11.0.0 | 55 | 11/11/2026 |
| 10.0.1 | 10,727 | 11/19/2025 |
| 10.0.0 | 728 | 11/19/2025 |
| 8.0.0 | 67,757 | 12/6/2023 |
| 7.0.0 | 14,756 | 11/9/2022 |
| 6.0.1 | 43,161 | 11/24/2021 |
| 6.0.0 | 9,330 | 11/24/2021 |
| 5.1.1 | 28,239 | 11/30/2020 |
| 5.1.0 | 1,181 | 11/30/2020 |
| 5.0.2 | 1,076 | 11/27/2020 |
| 5.0.1 | 1,172 | 11/20/2020 |
| 5.0.0 | 2,234 | 11/20/2020 |
| 4.0.0 | 106,542 | 11/11/2019 |
| 3.5.0 | 33,793 | 7/5/2019 |
| 3.4.0 | 23,902 | 3/13/2019 |
| 3.3.1 | 2,223 | 3/13/2019 |
| 3.3.0 | 29,414 | 10/19/2018 |
| 3.2.0 | 1,716 | 10/19/2018 |
| 3.1.0 | 3,606 | 10/15/2018 |
| 3.0.1 | 2,202 | 10/1/2018 |
.NET 11.0 support added and .NET 8.0 and .NET 9.0 support dropped