This article is the second part for Create Angular Project and Communicate with .Net Core
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:
//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
}
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
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;
}
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);
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);
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
The post Create Paging Data from .Net Core Api first appeared on Coder Blog.