Library / SDK
udndc/X.PagedList avatar
udndc/X.PagedList

X.PagedList: paging IEnumerable and IQueryable in ASP.NET

Library for easily paging through any IEnumerable/IQueryable in ASP.NET

926 stars220 forksC#MIT

At a glance

What is it?
X.PagedList is a fork of Troy Goode's PagedList rebuilt for the modern .NET platform, chopping an IEnumerable or IQueryable into pages that can be fetched by index and rendered with a pager control in MVC views. It fits teams with an existing PagedList codebase moving forward, and it does not fit a new project that is happy with the paging that ships with the framework itself.
Who is it for?
Adopt X.PagedList if you are maintaining an ASP.NET application that already uses PagedList and want to keep the pager markup and the calling patterns while moving to a current .NET target. Skip it if you are starting from scratch, because the framework's own Skip, Take and Pager support covers the same ground without a dependency.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A fork of PagedList, rebuilt for the current .NET

X.PagedList is a fork of Troy Goode's PagedList project. That relationship is stated first in the project documentation and it defines both the appeal and the constraint.

The appeal is continuity. The original PagedList was built for the ASP.NET MVC framework of its era, and a large number of applications grew up around its calling patterns and its pager markup. X.PagedList's stated difference from that ancestor is that it supports the modern .NET platform, so it can be used everywhere the .NET platform is supported rather than only in the older stack it came from.

The constraint is that a fork inherits decisions. The API shape, the naming and the pager control you would be porting are the ones users of the original library already know, which is exactly what makes the migration cheap and exactly what makes it unexciting. There is no new pagination model here, and no new concept to learn.

The project is MIT licensed, with the licence in a LICENSE.md file at the root of the repository, and it is published on NuGet as X.PagedList. The repository also carries CHANGELOG.md, CONTRIBUTING.md and SECURITY.md, and the top level includes a solution file in the newer .slnx format, alongside src/, tests/ and an examples/ directory with two projects, Example.DAL for the data access layer and Example.Website for the web side.

Chopping a sequence into pages and taking one by index

The core of the library is small and easy to describe. It takes an IEnumerable or an IQueryable, splits the sequence into pages, and lets you grab a specific page by index.

Working over IQueryable is the part that matters in a web application, because a queryable sequence stays a queryable sequence until it is enumerated. That means the page operation can be pushed into the database as a limit and offset rather than materialising the whole result set in the application and slicing it in memory. The distinction decides whether a paging link is cheap or expensive, and it is the reason a library that accepts both types is worth having.

Working over IEnumerable covers the cases where the sequence is already in memory, or is a computed sequence that has no query provider behind it, and the same paging call shape applies.

The documentation itself is thin on this point, and the project is upfront about where the detail lives. The readme says you can find all information about how to use the X.PagedList libraries in the project wiki. That is a real limitation for an evaluation, because the readme tells you the shape of the API without giving you the signatures, the pager configuration options, or the query string behaviour, and the wiki is a separate place that has to be read before you can judge whether the defaults suit your routes.

One consequence worth anticipating is that a pager that renders links has to agree with your routing and query string conventions. Any pager control carries that concern, and it is the first thing to check against your own URL scheme once you have the library installed.

PagedList.Mvc and the rendered pager

The library is split into more than one piece, and the split is the useful part of the design. The paging core deals with sequences. PagedList.Mvc is the layer that takes a page and displays a pager control with links such as Previous and Next.

Separating the two means the decision about how the pager looks and where its links point is kept out of the data access code. A controller action produces a page, and the view decides how to render the navigation for it. The topics attached to the repository reflect that structure, listing asp-net-core, asp-net-core-mvc, asp-net-mvc, pager-configurations, paginator and pagination.

The pager configuration is a real surface rather than a fixed widget, since the topic list includes pager-configurations as a separate concern. That matters in practice, because the default Previous and Next links are rarely enough. A results page that needs to show the current page number, a jump-to-page box, a first and last link, and a range of numbered pages has to be configured, and the amount of work to do that is what separates a usable pager from a checkbox one.

The examples directory gives a hint at the intended shape, since a project named Example.DAL and one named Example.Website mirror the split between fetching a page and rendering the navigation for it.

Getting the package and finding the usage details

There is no install command in the project documentation, so there is nothing to copy into a terminal here. The package is distributed on NuGet, and the readme links the NuGet listing for X.PagedList, alongside the wiki that carries the usage information.

That is the honest shape of this project as a piece of documentation. The readme is a signpost: what the library is, that it is a fork, that the usage lives in the wiki, and how to support the project. Everything a developer needs to make the decision is not there, and everything a developer needs to use it is in another repository section.

If you are evaluating it, the sequence is short. Read the wiki for the calling conventions and the pager configuration options, add the package to a scratch project, and render a pager against a real queryable source with a known row count. That last step is the one that matters, because it is where a pager's behaviour with an unknown total row count, an out-of-range page index, or an empty result set shows up, and none of those behaviours are described in the readme.

The repository does contain a CHANGELOG.md, which is the right file to read before upgrading, and SECURITY.md for how to report a vulnerability in the library.

One maintainer, a version line that moves slowly

The support section of the readme is short and unusually direct about the project's shape. It states that X.PagedList is used in over 15 million installs and maintained by one person in his spare time, and that sponsoring directly funds issue triage, .NET version support and documentation.

Treat that install figure as the maintainer's own claim rather than as a quality measure. What it does indicate is reach: this is a library with a large installed base, which is exactly why a fork with a maintained release line exists.

The version history explains the cadence. The recent releases are v10.6.0 on 2026-09-06, v10.5.9 on 2025-08-18 and v10.5.7 on 2024-10-27. The repository is not archived, the default branch is master, and the last push was on 2026-10-15, so work is happening on the branch even in months when no release was cut.

The 10.x numbering with a patch release that advances the minor component is a pattern worth noting if you pin versions. The last push lands days after the v10.6.0 tag, so the master branch contains work that is not in any published package, and building from the branch is a different proposition from consuming the NuGet release.

The sponsorship model extends into support tiers. The readme describes a Corporate tier that includes priority triage and advance notice of breaking changes, which is the mechanism a using organisation would rely on if it needs to know about a .NET version drop before it lands. It is a good fit for a library with a single maintainer, since the commercial tier is what funds the work that the free tier cannot prioritise.

When the framework's own paging is enough

The honest comparison for a new project is not another pagination library, it is doing it yourself with what the framework already provides. ASP.NET Core includes LINQ query operators for skipping and taking records, and it ships a pager tag helper and view support for rendering page navigation, so a results page with Skip, Take and a Pager tag is a small amount of code.

The difference in approach is where the abstraction sits. The built-in path gives you the query operators and a rendering helper, and you assemble the page metadata yourself. X.PagedList gives you a page type that carries the pagination state alongside the items, plus a configured pager control that knows how to render Previous and Next links and the page range. For a project that has to produce a consistent pager across many screens, a shared abstraction and a shared look beat assembling the same metadata by hand each time.

That is also exactly the case for a project that already uses PagedList, and the case where the cost of migrating is highest. Porting an existing application to hand-rolled paging means touching every action that returns a page and every view that renders a pager, and it means re-implementing the edge cases that the library already handles. Keeping X.PagedList and moving the target framework is the smaller change.

The failure mode to watch for in either case is the same. A pager that renders a page number but issues a count query on every request turns an indexable page into a full scan, and neither approach prevents that. Whichever route you take, the count belongs in a cached or estimated form rather than in the request path, and the difference between the two libraries on that point is nil.

Editorial conclusion

Adopt X.PagedList if you are maintaining an ASP.NET application that already uses PagedList and want to keep the pager markup and the calling patterns while moving to a current .NET target. Skip it if you are starting from scratch, because the framework's own Skip, Take and Pager support covers the same ground without a dependency. Verify first which major version of the package your project resolves to, since the release numbering has moved through the 10.x line while the code lineage goes back to the original PagedList project, and read the wiki rather than the readme before you wire the pager into a view.

Frequently asked questions

What is the difference between X.PagedList and the original PagedList?

X.PagedList is a fork of Troy Goode's PagedList project. The stated main difference is that X.PagedList supports the modern .NET platform, so it can be used everywhere the .NET platform is supported, while keeping the paging API and the MVC pager control.

How do I install X.PagedList?

The package is published on NuGet as X.PagedList and the project documentation links the NuGet listing. The readme itself contains no install command, and points to the project wiki for all usage information.

Can X.PagedList page a database query efficiently?

It accepts both IEnumerable and IQueryable. When the source is an IQueryable the sequence stays a queryable sequence until it is enumerated, which is what allows the paging operation to be applied as part of the query rather than by materialising the whole result set first.

How is X.PagedList maintained and licensed?

It is MIT licensed and maintained by one person in his spare time, with sponsoring funding issue triage, .NET version support and documentation, and a corporate tier offering priority triage and advance notice of breaking changes. The last push was on 2026-10-15 and the recent releases include v10.6.0 on 2026-09-06.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. udndc/X.PagedList on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/udndc-x-pagedlist.svg)](https://hysenlabs.com/projects/udndc-x-pagedlist)