Implementation of paging function of ABP entry series

Time:2021-12-30

After completing the addition, deletion, modification and query of the task list, let’s talk about the essential paging function.

First of all, I’m glad ABP has helped us encapsulate the paging implementation. It’s really considerate.

In this section, let’s take a look at how to use ABP for paging.

1. Paging request dto definition

Data transfer objects are used for data transfer of application layer and presentation layer.

The presentation layer passes in a data transfer object (dto) to call an application service method, and then the application service executes some specific business logic through the domain object and returns the dto to the presentation layer. In this way, the presentation layer and domain layer are completely separated. In an application with good layering, the presentation layer does not directly use domain objects (warehouses, entities).

When there is a paging request in the presentation layer, we generally need to specify two parameters, one is to mark the page and the other is the number of lines per page (generally configured with a configuration file).

Because paging is a very common function, when we have paging requests in the presentation layer, we’d better have corresponding DTOs to encapsulate these two parameters.

The ABP source code does not encapsulate such a common class for us, but in the abpzero project, the corresponding paging dto is defined.

The corresponding class diagram is as follows:

Page sorting and filtering corresponding dto class diagram

It can be seen that it mainly includes the following four public dto definitions:

  1. Pagedinputdto: paging request dto
  2. Pagedandsortedinputdto: page sorting dto
  3. Pagedsortedandfilteredinputdto: paging sort filter dto
  4. Pagedandfilteredinputdto: page filter dto

Is it very practical? Our paging is generally mixed with filtering and sorting.

The following main attributes are defined:

  • Maxresultcount: the number of rows per page, which can be read from the defined configuration.
  • Skipcount: jump quantity. The general calculation formula is skipcount = Page * maxresultcount (pages * rows).
  • Filter: filter string
  • Sorting: sorting by

The specific implementation will not be detailed. I believe that if you look at the class diagram carefully, you can implement it yourself. Abpzero defines these public DTOs in the dto folder of the application service layer. The specific path is shown in the figure below.

2. How to use paging dto

Take our task list as an example. We modify it and create itGetTaskInputDto, let it inherit fromPagedSortedAndFilteredInputDto, soGetTaskInputDtoYou have the properties required for paging sorting and filtering.


public class GetTasksInput : PagedSortedAndFilteredInputDto
{
 public TaskState? State { get; set; }
 public int? AssignedPersonId { get; set; }
}

3. Return paging result dto

ABP has defined a generic pagedresultdto for us to wrap the returned paging results. It mainly includes two attributes: int totalcount saves the total number, and ireadonlylist < T > items saves the returned paging result set.

4. Application service layer paging logic implementation

1. Define the interface in itaskappservice


PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input);

2. Implement the interface in taskappservice:

public PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input)
{
 //Preliminary filtration
 var query = _taskRepository.GetAll().Include(t => t.AssignedPerson)
  .WhereIf(input.State.HasValue, t => t.State == input.State.Value)
  .WhereIf(!input.Filter.IsNullOrEmpty(), t => t.Title.Contains(input.Filter))
  .WhereIf(input.AssignedPersonId.HasValue, t => t.AssignedPersonId == input.AssignedPersonId.Value);
 //Sort
 query = !string.IsNullOrEmpty(input.Sorting) ? query.OrderBy(input.Sorting) : query.OrderByDescending(t => t.CreationTime);
 //Get total
 var tasksCount = query.Count();
 //Default paging mode
 //var taskList = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();
 //ABP provides the extension method pageby paging mode
 var taskList = query.PageBy(input).ToList();
 return new PagedResultDto<TaskDto>(tasksCount,taskList.MapTo<List<TaskDto>>());
}

The implementation of paging is very simple. First filter, sort, and then paging. Finally, pagedresultdto is used to encapsulate the paging results.

Carefully, you may find two methods that have not been used in LINQWhereIfandPageByYes, this is the extension method provided by ABP. Those interested can see the source codeQueryableExtensionsThe specific implementation of LINQ is actually very simple, but we may not think of it when using LINQ.

Here are some questions:

How many queries have been made in this code?

What paging technology is used in the code? (true paging? False paging?)

5. Use x.pagedlist for front-end paging

In ASP Net MVC has a series of open source implementations for front-end paging, and the open source X. pagedlist paging is used in my demo. For specific source code, please refer to X. pagedlist GitHub.

1. Please install x.pagedlist.xml in your web project yourself MVC nuget package

X.PagedList. MVC nuget package

2. Use the method provided by X. pagedlist in the controller to construct paging results for front-end use

Because we have manually implemented paging logic in the application service layer, we need to construct staticpagedlist as the return result according to the example on the official website of X. pagedlist.

public ActionResult PagedList(int? page)
 {
  //Lines per page
  var pageSize = 5;
  var pageNumber = page ??  1;// What page
  var filter = new GetTasksInput
  {
   Skipcount = (PageNumber - 1) * PageSize, // number ignored
   MaxResultCount = pageSize
  };
  var result = _taskAppService.GetPagedTasks(filter);
  //The paging logic has been completed manually in the application service layer, so the paging results need to be constructed manually
  var onePageOfTasks = new StaticPagedList<TaskDto>(result.Items, pageNumber, pageSize, result.TotalCount);
  //Put the paging results into viewbag for view to use
  ViewBag.OnePageOfTasks = onePageOfTasks;
  return View();
}

From the code, we can see that after constructing the paging results provided by X. pagedlist, we put them into the viewbag for the view.

3. Add paging control to view

The code of pagedlist view is as follows:


@using X.PagedList.Mvc;
@using Abp.Web.Mvc.Extensions
@using X.PagedList; 
<link href="~/Content/PagedList.css" rel="external nofollow" rel="stylesheet" />
<ul>
 @foreach (var task in ViewBag.OnePageOfTasks)
 {
  <li>
   <div>
    <button type="button">Edit</button>
    <button type="button">Delete</button>
   </div>
   <div>
    <a href="#" rel="external nofollow" >
     @*<i></i>*@
    </a>
    <div>
     <h4>@task.Title</h4>
     <span>@task.CreationTime.ToString("yyyy-MM-dd HH:mm:ss")</span>
    </div>
   </div>
  </li>
 }
</ul>
@Html.PagedListPager((IPagedList)ViewBag.OnePageOfTasks, page => Url.Action("PagedList", new { page }))

The last sentence of the code is used to generate paging controls.

The final effect is shown in the figure:

summary

summary

This section mainly explains how to use ABP for background paging, and also explains the implementation of ABP background paging logic. It also demonstrates how to use X. pagedlist for front-end paging.