Create Paging Data from .Net Core Api

  1. How to setup VS Code environment for ASP.NET Core Project
  2. Use code first to connect database in .Net Core API
  3. Use the Repository pattern in .Net core
  4. Create .Net Core Api controller for CRUD with repository
  5. Use the Serilog in .Net Core
  6. Create Angular Project and Communicate with .Net Core
  7. Create Paging Data from .Net Core Api
  8. How to do Unit Testing for the Core Api Project with Repository

This article is the second part for Create Angular Project and Communicate with .Net Core

1. Data Result Service

As we need to support filter and paging data from Api, so we also need to create a date result service for handle it. We can create this service in MyDemo.Core Api project:

1.1. Create the properties for filter and paging

//MyDemo.API/MyDemo.Core/Services/DataResultService.cs

public class DataResultService<T>
{
   #region Properties
    /// <summary>
    /// The data result.
    /// </summary>
    public List<T> Data { get; private set; }

    /// <summary>
    /// Zero-based index of current page.
    /// </summary>
    public int PageIndex { get; private set; }

    /// <summary>
    /// Number of items contained in each page.
    /// </summary>
    public int PageSize { get; private set; }

    /// <summary>
    /// Total items count
    /// </summary>
    public int TotalCount { get; private set; }

    /// <summary>
    /// Total pages count
    /// </summary>
    public int TotalPages { get; private set; }

    /// <summary>
    /// TRUE if the current page has a previous page,
    /// FALSE otherwise.
    /// </summary>
    public bool HasPreviousPage
    {
        get
        {
            return (PageIndex > 0);
        }
    }

    /// <summary>
    /// TRUE if the current page has a next page, FALSE otherwise.
    /// </summary>
    public bool HasNextPage
    {
        get
        {
            return ((PageIndex + 1) < TotalPages);
        }
    }

    /// <summary>
    /// Sorting Column name (or null if none set)
    /// </summary>
    public string? SortColumn { get; set; }

    /// <summary>
    /// Sorting Order ("ASC", "DESC" or null if none set)
    /// </summary>
    public string? SortOrder { get; set; }

    /// <summary>
    /// Filter Column name (or null if none set)
    /// </summary>
    public string? FilterColumn { get; set; }
    /// <summary>
    /// Filter Query string
    /// (to be used within the given FilterColumn)
    /// </summary>
    public string? FilterQuery { get; set; }
    #endregion
}

1.2. Create a private constructor

We need to return the data object for client side and include the above properties, so we can use a private constructor for return the data

Do you want to be a good trading in cTrader?   >> TRY IT! <<
private DataResultService(
    List<T> data,
    int count,
    int pageIndex,
    int pageSize,
    string? sortColumn,
    string? sortOrder,
    string? filterColumn,
    string? filterQuery)
{
    Data = data;
    PageIndex = pageIndex;
    PageSize = pageSize;
    TotalCount = count;
    TotalPages = (int)Math.Ceiling(count / (double)pageSize);
    SortColumn = sortColumn;
    SortOrder = sortOrder;
    FilterColumn = filterColumn;
    FilterQuery = filterQuery;
}

1.3. Get paging data

Cause I want to support dynamic filter with Linq, so we need to create a method for handle this, and need to install below packages from Nuget for support dynamic filter query

System.Linq.Dynamic.Core
System.Linq.Async

Now we can create the below method

public static async Task<DataResultService<T>> CreateAsync(
            IQueryable<T> source,
            int pageIndex,
            int pageSize,
            string? sortColumn = null,
            string? sortOrder = null,
            string? filterColumn = null,
            string? filterQuery = null)
        {
          //todo...
        }

this method can support many parameters from client side, because these parameters were passed from client by a Get method with a string format, so the first thing we need to do is split the column and query, after that, just create a dynamic SQL query pass to Linq object for get data

if (!string.IsNullOrEmpty(filterColumn)
    && !string.IsNullOrEmpty(filterQuery))
{
    if (filterColumn.Contains(","))
    {
        //handle multiple columns filter
        var index = 0;
        var sql = "";
        var queries = filterQuery.Split(',');
        foreach (var column in filterColumn.Split(','))
        {
            if (!string.IsNullOrEmpty(queries[index]) && queries[index] != "null")
            {
                sql += string.Format("{0}.Contains(@{1}) and ", column, index);
            }
            index++;
        }
        if (sql.Length > 0)
        {
            sql = sql.Substring(0, sql.Length - 4); //remove the end of 'and '
        }
        if (sql != "")
        {
            source = source.Where(sql, queries);
        }
    }
    else
    {
        source = source.Where(
        string.Format("{0}.Contains(@0)",
        filterColumn),
        filterQuery);
    }
}

get the total items and generate the data for paging

var count = await source.CountAsync();

//sort data by column 
if (!string.IsNullOrEmpty(sortColumn))
{
    sortOrder = !string.IsNullOrEmpty(sortOrder)
    && sortOrder.ToUpper() == "ASC" ? "ASC" : "DESC";

    source = source.OrderBy(string.Format("{0} {1}",sortColumn,sortOrder));
}

//get the data by paging query
source = source.Skip(pageIndex * pageSize).Take(pageSize);

//convert to list items
var data = await source.ToAsyncEnumerable().ToListAsync();

//generate the result by private constructor
return new DataResultService<T>(
            data,
            count,
            pageIndex,
            pageSize,
            sortColumn,
            sortOrder,
            filterColumn,
            filterQuery);

2. Update UserController

After created the DataResultService , we can update our UserController.

First, update the GetUsers for support paging parameters, and change the return value to DataResultService<User>

public async Task<ActionResult<DataResultService<User>>> GetUsers(
                        int pageIndex = 0, int pageSize = 10,
                        string? sortColumn = null, string? sortOrder = null,
                        string? filterColumn = null, string? filterQuery = null)

update the apiResult type to DataResultService<User>

var apiResult = new ApiResult<DataResultService<User>>();

in the end, update the get data method

var users = _userRepository.GetAll();

apiResult.Data = await DataResultService<User>.CreateAsync(
            users,
            pageIndex,
            pageSize, sortColumn,
            sortOrder, filterColumn,
            filterQuery);

3. Test the Api

Ok, we have finished the changes with our Api, now we can try it with the angular client.

First, start the Api project in VS Code console with below command (don’t forget goto the Api folder)

dotnet watch run

and create another new console and goto MyDemo.Client folder to run below command

npm run hmr

after that, you should access the user management page as below URL

http://localhost:4810/user-management

and if everything is ok, the result should be like below

after search by user name

Loading

Views: 58
Total Views: 454 ,

Leave a Reply

Your email address will not be published. Required fields are marked *