Skip to content

Paging Control #641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mjartz opened this issue Nov 27, 2019 · 1 comment · Fixed by #642
Closed

Paging Control #641

mjartz opened this issue Nov 27, 2019 · 1 comment · Fixed by #642

Comments

@mjartz
Copy link

mjartz commented Nov 27, 2019

Description

In v3.1.0 I was able to set a global default page size to 20 in statup.cs which was desirable for most of my resources, however there were a few resources that I didn't want that default to apply to as I wanted every record returned by default, but still wanted paging if a page size was supplied by the client. I was able to achieve this in the controller for the given resource by checking whether a page size was supplied in the context QuerySet, and if not, I would set the context PageManager.PageSize = 0.

public class MyEntityController : BaseJsonApiController<MyEntity>
{
     public MyEntityController(
           IJsonApiContext jsonApiContext,
           IResourceService<MyEntity> resourceService,
           ILoggerFactory loggerFactory)
           : base(jsonApiContext, resourceService, loggerFactory)
       {
           if (jsonApiContext.QuerySet == null || jsonApiContext.QuerySet.PageQuery.PageSize == 0)
               jsonApiContext.PageManager.PageSize = 0;
       }
}

This worked well, but I am unable to achieve this in v4.0.0 using the PageService. I read in a previous issue (#217) of a potential solution to introduce a pagination attribute that could be used on resource definitions and I think this would be great as long as it allowed me to override the global default page size to something different, including equal to zero for no paging by default.

The above is probably a bigger change, so another option might be to:
Modify the PageService class as follows:

  • Expose a DefaultPageSize property, defaulted to the global DefaultPageSize value
  • Change the PageSize property to a int? and do not initialize it in the constructor
  • Set the PageSize property to the value parsed from query parameters, only if supplied
  • Add a CalcPageSize property { get => PageSize ?? DefaultPageSize; }

Modify the DefaultResourceService class, ApplyPageQueryAsync method as follows:

protected virtual async Task<IEnumerable<TResource>> ApplyPageQueryAsync(IQueryable<TResource> entities)
{
    if (_pageService.CalcPageSize == 0)
    {
        var allEntities = await _repository.ToListAsync(entities);
        return allEntities as IEnumerable<TResource>;
    }

    int pageOffset = _pageService.CurrentPage;
    if (_pageService.Backwards)
    {
        pageOffset = -pageOffset;
    }
    if (_logger?.IsEnabled(LogLevel.Information) == true)
    {
        _logger?.LogInformation($"Applying paging query. Fetching page {pageOffset} " +
            $"with {_pageService.CalcPageSize} entities");
    }

    return await _repository.PageAsync(entities, _pageService.CalcPageSize, pageOffset);
}

This respects the global default page size and any page sizes supplied in query parameters, but also allows me to modify the page service in a custom resource service to set PageSize = 0 to default to no paging.

public class MyEntityService : DefaultResourceService<MyEntity>
{
    public MyEntityService(
        IEnumerable<IQueryParameterService> queryParameters,
        IJsonApiOptions options,
        IResourceRepository<MyEntity> repository,
        IResourceContextProvider provider,
        ILoggerFactory loggerFactory = null)
        : base(queryParameters, options, repository, provider, null, loggerFactory)
    {
        var pageService = queryParameters.FirstOrDefault<IPageService>();
        pageService.PageSize = 0;
    }
}

I could also set a different DefaultPageSize for a given entity service as well if i wanted it different to the global option.

Thanks guys and keep up the great work.

Environment

  • JsonApiDotNetCore Version: 4.0.0.0 alpha 4
  • Other Relevant Package Versions:
maurei added a commit that referenced this issue Nov 28, 2019
@maurei
Copy link
Member

maurei commented Nov 28, 2019

Hi @mjartz, thanks for the clear feedback. Indeed, DefaultPageSize was exposed before and I wasn't sure why that was, but this appears to be a valid use-case for that.

The proposed attribute in #217 is nice, but currently not very high up my todo-list. I processed your request in #642 :)

Cheers

@maurei maurei mentioned this issue Nov 28, 2019
wisepotato pushed a commit that referenced this issue Nov 28, 2019
On IPageService, exposes DefaultPageSize next to the RequestedPageSize to give the user more control over pagination.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants