如何在 ASP.NET Core Web API 中实现搜索过滤器
How to implement search filter in ASP.NET Core Web API
在我的 ASP.NET Core-6 Web API 中,我有这两个模型:
public class Department
{
public int Id { get; set; }
public string DepartmentName { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string StaffNumber { get; set; }
public int DepartmentId { get; set; }
public Department Department { get; set; }
}
为了能够进行分页,我有这些 类:
public class Result
{
internal Result(bool succeeded, IEnumerable<string> errors)
{
Succeeded = succeeded;
Errors = errors.ToArray();
}
public bool Succeeded { get; set; }
public string[] Errors { get; set; }
public static Result Success()
{
return new Result(true, new string[] { });
}
public static Result Failure(IEnumerable<string> errors)
{
return new Result(false, errors);
}
}
public class PaginatedList<T>
{
public List<T> Items { get; }
public int PageIndex { get; }
public int TotalPages { get; }
public int TotalCount { get; }
public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
TotalCount = count;
Items = items;
}
public bool HasPreviousPage => PageIndex > 1;
public bool HasNextPage => PageIndex < TotalPages;
public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize, CancellationToken cancellationToken)
{
var count = await source.CountAsync(cancellationToken);
var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(cancellationToken);
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
我正在使用 Entity Framework,这是最终代码:
public class GetAllEmployeesWithPaginationQuery : IRequestWrapper<PaginatedList<EmployeeDto>>
{
public int DepartmentId { get; set; }
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
public class GetAllEmployeesWithPaginationQueryHandler : IRequestHandlerWrapper<GetAllEmployeesWithPaginationQuery, PaginatedList<EmployeeDto>>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
public GetAllEmployeesWithPaginationQueryHandler(IApplicationDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public async Task<ServiceResult<PaginatedList<EmployeeDto>>> Handle(GetAllEmployeesWithPaginationQuery request, CancellationToken cancellationToken)
{
PaginatedList<EmployeeDto> list = await _context.Employees
.Where(x => x.DepartmentId == request.DepartmentId)
.OrderBy(o => o.Name)
.ProjectToType<EmployeeDto>(_mapper.Config)
.PaginatedListAsync(request.PageNumber, request.PageSize, cancellationToken);
return list.Items.Any() ? ServiceResult.Success(list) : ServiceResult.Failed<PaginatedList<EmployeeDto>>(ServiceError.NotFound);
}
}
我已成功完成分页,但需要使用以下字段进行排序和搜索筛选:FirstName、LastName、StaffNumber 和 DepartmentName。
我该如何实现?
谢谢。
声明一个 QueryObject class,此 class 映射您的传入查询
例如 /api/SearchEmployees?firstName=mark&sortBy=name&isSortAscending=true&page=2&pageSize=10
将映射到此 class
public class QueryObject
{
public int? Id { get; set; }
public string FirstName { get; set; }
public string LastName {get;set;}
public string Abbr { get; set; }
public bool IsSortAscending { get; set; }
public string SortBy { get; set; }
public int Page { get; set; }
public int? PageSize { get; set; }
}
//在你的控制器中做这样的事情:
public List<Employee> GetEmployee(QueryObject query)
{
var employees = _context.Employees.AsQueryable();
if(!string.IsNullOrEmpty(query.FirstName))
{
employees = employees.Where(e => e.Name.Contains(query.Name));
}
var ColumnsMap = new Dictionary<string, Expression<Func<Province, object>>>
{
["name"] = c => c.Name,
["abbr"] = c => c.
};
employees = employees.ApplyOrdering(query, ColumnsMap);
//Do paging as you have done earlier
return employees.ToList();
}
//This function orders based on the key and Expression Function You pass
public static IQueryable<T> ApplyOrdering<T>(this IQueryable<T> query, QueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
{
if (string.IsNullOrWhiteSpace(queryObj.SortBy) || !columnsMap.ContainsKey(queryObj.SortBy))
return query;
return queryObj.IsSortAscending ? query.OrderBy(columnsMap[queryObj.SortBy]) : query.OrderByDescending(columnsMap[queryObj.SortBy]);
}
在我的 ASP.NET Core-6 Web API 中,我有这两个模型:
public class Department
{
public int Id { get; set; }
public string DepartmentName { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string StaffNumber { get; set; }
public int DepartmentId { get; set; }
public Department Department { get; set; }
}
为了能够进行分页,我有这些 类:
public class Result
{
internal Result(bool succeeded, IEnumerable<string> errors)
{
Succeeded = succeeded;
Errors = errors.ToArray();
}
public bool Succeeded { get; set; }
public string[] Errors { get; set; }
public static Result Success()
{
return new Result(true, new string[] { });
}
public static Result Failure(IEnumerable<string> errors)
{
return new Result(false, errors);
}
}
public class PaginatedList<T>
{
public List<T> Items { get; }
public int PageIndex { get; }
public int TotalPages { get; }
public int TotalCount { get; }
public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
TotalCount = count;
Items = items;
}
public bool HasPreviousPage => PageIndex > 1;
public bool HasNextPage => PageIndex < TotalPages;
public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize, CancellationToken cancellationToken)
{
var count = await source.CountAsync(cancellationToken);
var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(cancellationToken);
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
我正在使用 Entity Framework,这是最终代码:
public class GetAllEmployeesWithPaginationQuery : IRequestWrapper<PaginatedList<EmployeeDto>>
{
public int DepartmentId { get; set; }
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
public class GetAllEmployeesWithPaginationQueryHandler : IRequestHandlerWrapper<GetAllEmployeesWithPaginationQuery, PaginatedList<EmployeeDto>>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
public GetAllEmployeesWithPaginationQueryHandler(IApplicationDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public async Task<ServiceResult<PaginatedList<EmployeeDto>>> Handle(GetAllEmployeesWithPaginationQuery request, CancellationToken cancellationToken)
{
PaginatedList<EmployeeDto> list = await _context.Employees
.Where(x => x.DepartmentId == request.DepartmentId)
.OrderBy(o => o.Name)
.ProjectToType<EmployeeDto>(_mapper.Config)
.PaginatedListAsync(request.PageNumber, request.PageSize, cancellationToken);
return list.Items.Any() ? ServiceResult.Success(list) : ServiceResult.Failed<PaginatedList<EmployeeDto>>(ServiceError.NotFound);
}
}
我已成功完成分页,但需要使用以下字段进行排序和搜索筛选:FirstName、LastName、StaffNumber 和 DepartmentName。
我该如何实现?
谢谢。
声明一个 QueryObject class,此 class 映射您的传入查询
例如 /api/SearchEmployees?firstName=mark&sortBy=name&isSortAscending=true&page=2&pageSize=10
将映射到此 class
public class QueryObject
{
public int? Id { get; set; }
public string FirstName { get; set; }
public string LastName {get;set;}
public string Abbr { get; set; }
public bool IsSortAscending { get; set; }
public string SortBy { get; set; }
public int Page { get; set; }
public int? PageSize { get; set; }
}
//在你的控制器中做这样的事情:
public List<Employee> GetEmployee(QueryObject query)
{
var employees = _context.Employees.AsQueryable();
if(!string.IsNullOrEmpty(query.FirstName))
{
employees = employees.Where(e => e.Name.Contains(query.Name));
}
var ColumnsMap = new Dictionary<string, Expression<Func<Province, object>>>
{
["name"] = c => c.Name,
["abbr"] = c => c.
};
employees = employees.ApplyOrdering(query, ColumnsMap);
//Do paging as you have done earlier
return employees.ToList();
}
//This function orders based on the key and Expression Function You pass
public static IQueryable<T> ApplyOrdering<T>(this IQueryable<T> query, QueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
{
if (string.IsNullOrWhiteSpace(queryObj.SortBy) || !columnsMap.ContainsKey(queryObj.SortBy))
return query;
return queryObj.IsSortAscending ? query.OrderBy(columnsMap[queryObj.SortBy]) : query.OrderByDescending(columnsMap[queryObj.SortBy]);
}