Pagination in APIs with Razor
Pagination in APIs
Make a PaginationRequest.cs and put this in it:
namespace eShop.Catalog.API.Model;
public record PaginationRequest(int PageSize = 10, int PageIndex = 0);
------------------------------------
namespace eShop.Catalog.API.Model;
public class PaginatedItems<TEntity>(int pageIndex, int pageSize, long count, IEnumerable<TEntity> data) where TEntity : class
{
public int PageIndex { get; } = pageIndex;
public int PageSize { get; } = pageSize;
public long Count { get; } = count;
public IEnumerable<TEntity> Data { get;} = data;
}
------------------------------------
Pagination only really applies to the GetAll(), GetItemsByName(), or GetAllByType() methods. Not needed on create, delete, update, or GetById().
So in your:
api.MapGet("/items", GetAllItems);
you need to implement GetAllItems() as such:
public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
[AsParameters] PaginationRequest paginationRequest,
[AsParameters] CatalogServices services)
{
var pageSize = paginationRequest.PageSize;
var pageIndex = paginationRequest.PageIndex;
var totalItems = await services.Context.CatalogItems
.LongCountAsync();
var itemsOnPage = await services.Context.CatalogItems
.OrderBy(c => c.Name)
.Skip(pageSize * pageIndex)
.Take(pageSize)
.ToListAsync();
return TypedResults.Ok(new PaginatedItems<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage));
}
----------------------
CATALOG.RAZOR
@page "/"
@inject NavigationManager Nav
@inject eShop.HybridApp.Services.CatalogService CatalogService
<PageTitle>AdventureWorks</PageTitle>
<SectionContent SectionName="page-header-title">Ready for a new adventure?</SectionContent>
<SectionContent SectionName="page-header-subtitle">Start the season with the latest in clothing and equipment.</SectionContent>
<div class="catalog">
<eShop.HybridApp.Components.Pages.Catalog.CatalogSearch BrandId="@BrandId" ItemTypeId="@ItemTypeId" />
@if (catalogResult is null)
{
<p>Loading...</p>
}
else
{
<div>
<div class="catalog-items">
@foreach (var item in catalogResult.Data)
{
<CatalogListItem Item="@item" />
}
</div>
<div class="page-links">
@foreach (var pageIndex in GetVisiblePageIndexes(catalogResult))
{
<NavLink ActiveClass="active-page" Match="@NavLinkMatch.All" href="@Nav.GetUriWithQueryParameter("page", pageIndex == 1 ? null : pageIndex)">@pageIndex</NavLink>
}
</div>
</div>
}
</div>
@code {
const int PageSize = 9;
[SupplyParameterFromQuery]
public int? Page { get; set; }
[SupplyParameterFromQuery(Name = "brand")]
public int? BrandId { get; set; }
[SupplyParameterFromQuery(Name = "type")]
public int? ItemTypeId { get; set; }
CatalogResult? catalogResult;
static IEnumerable<int> GetVisiblePageIndexes(CatalogResult result)
=> Enumerable.Range(1, (int)Math.Ceiling(1.0 * result.Count / PageSize));
protected override async Task OnParametersSetAsync()
{
catalogResult = await CatalogService.GetCatalogItems(
Page.GetValueOrDefault(1) - 1,
PageSize,
BrandId,
ItemTypeId);
}
}
Comments
Post a Comment