一、功能说明
- 当前端传入分页查询信息时,会校验并修改请求分页的信息
ini
public class RequestPage
{
public string? keyword { get; set; }
private const int maxSize = 20;
private int _pageNumber = 1;
public int pageNumber
{
get => _pageNumber;
set => _pageNumber = value < 1 ? 1 : value;
}
private int _pageSize = 10 ;
public int pageSize
{
get => _pageSize;
set => _pageSize = value < 1 ? 10 : ((value > maxSize) ? maxSize : value);
}
}
新建了一个类接受分页参数,实现了如下功能:
-
默认每页最大展示20条,并且当没有参数传入时,默认展示第1页的前10条数据
-
当传入的分页信息为负数时,展示第1页的前10条数据
- 默认会查询符合条件的所有信息,并且针对前端传递的pageSize和pageNumber截取并返回数据
csharp
public class ResponsePage<T>:List<T>
{
public int currentPage { get; private set; }
public int totalPages { get; private set; }
public int pageSize { get; private set; }
public int totalCount { get; private set; }
public bool hasPrevious => currentPage > 1;
public bool hasNext => currentPage < totalPages;
public ResponsePage(List<T> items,int count,int pageNumber,int pageSize)
{
totalCount = count;
pageSize = pageSize;
currentPage = pageNumber;
totalPages = (int)Math.Ceiling(count / (double)pageSize);
AddRange(items);
}
public static ResponsePage<T> Create(IQueryable<T> source,int pageNumber,int pageSize)
{
var count = source.Count();
var items = source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
return new ResponsePage<T>(items, count, pageNumber, pageSize);
}
}
使用演示:
ini
[HttpGet(Name = nameof(GetUserInfo))]
public object GetUserInfo([FromQuery]RequestPage? page)
{
// 初始化Bogus库
var faker = new Faker();
// 生成100个随机用户
var users = Enumerable.Range(1, 100).Select(i =>
new User
{
Name = faker.Name.FullName(),
Age = faker.Random.Int(18, 60),
Email = faker.Internet.Email()
});
// 将用户列表转换为IQueryable对象
var queryableUsers = users.AsQueryable();
ResponsePage<User> res = ResponsePage<User>.Create(queryableUsers, page.pageNumber, page.pageSize);
return res;
}
- 请求头会捎带
上一页
和下一页
的请求地址以及分页信息
ini
ResponsePage<User> res = ResponsePage<User>.Create(queryableUsers, page.pageNumber, page.pageSize);
var previousLink = res.hasPrevious
? CreateResourceUri(page, ResourceUriType.PreviousPage)
: null;
var nextLink = res.hasNext
? CreateResourceUri(page, ResourceUriType.NextPage)
: null;
var paginationMetadata = new
{
totalCount = res.totalCount,
pageSize = res.pageSize,
currentPage = res.currentPage,
totalPages = res.totalPages,
previousLink,
nextLink
};
ini
private string CreateResourceUri(RequestPage page, ResourceUriType type)
{
switch (type)
{
case ResourceUriType.PreviousPage:
return Url.Link(nameof(GetUserInfo), new
{
pageNumber = page.pageNumber - 1,
pageSize = page.pageSize,
keyword = page.keyword
});
case ResourceUriType.NextPage:
return Url.Link(nameof(GetUserInfo), new
{
pageNumber = page.pageNumber + 1,
pageSize = page.pageSize,
keyword = page.keyword
});
default:
return Url.Link(nameof(GetUserInfo), new
{
pageNumber = page.pageNumber + 1,
pageSize = page.pageSize,
keyword = page.keyword
});
}
}
请求第一页的前3条数据,因为这是第一页,所以没有上一页,返回Null;而下一页信息,只是在这次请求的基础修改了pageNumber + 1
二、核心代码
ini
using Bogus;
using MassTransit.Futures.Contracts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using System.Security.AccessControl;
using page_1.Controllers;
using System.Text.Encodings.Web;
using System.Text.Json;
namespace page_1.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet(Name = nameof(GetUserInfo))]
public object GetUserInfo([FromQuery]RequestPage? page)
{
// 初始化Bogus库
var faker = new Faker();
// 生成100个随机用户
var users = Enumerable.Range(1, 100).Select(i =>
new User
{
Name = faker.Name.FullName(),
Age = faker.Random.Int(18, 60),
Email = faker.Internet.Email()
});
// 将用户列表转换为IQueryable对象
var queryableUsers = users.AsQueryable();
ResponsePage<User> res = ResponsePage<User>.Create(queryableUsers, page.pageNumber, page.pageSize);
var previousLink = res.hasPrevious
? CreateResourceUri(page, ResourceUriType.PreviousPage)
: null;
var nextLink = res.hasNext
? CreateResourceUri(page, ResourceUriType.NextPage)
: null;
var paginationMetadata = new
{
totalCount = res.totalCount,
pageSize = res.pageSize,
currentPage = res.currentPage,
totalPages = res.totalPages,
previousLink,
nextLink
};
Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(paginationMetadata,
new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
return res;
}
private string CreateResourceUri(RequestPage page, ResourceUriType type)
{
switch (type)
{
case ResourceUriType.PreviousPage:
return Url.Link(nameof(GetUserInfo), new
{
pageNumber = page.pageNumber - 1,
pageSize = page.pageSize,
keyword = page.keyword
});
case ResourceUriType.NextPage:
return Url.Link(nameof(GetUserInfo), new
{
pageNumber = page.pageNumber + 1,
pageSize = page.pageSize,
keyword = page.keyword
});
default:
return Url.Link(nameof(GetUserInfo), new
{
pageNumber = page.pageNumber + 1,
pageSize = page.pageSize,
keyword = page.keyword
});
}
}
}
public enum ResourceUriType
{
PreviousPage, NextPage
}
// 定义一个用户类
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
public class RequestPage
{
public string? keyword { get; set; }
private const int maxSize = 20;
private int _pageNumber = 1;
public int pageNumber
{
get => _pageNumber;
set => _pageNumber = value < 1 ? 1 : value;
}
private int _pageSize = 10 ;
public int pageSize
{
get => _pageSize;
set => _pageSize = value < 1 ? 10 : ((value > maxSize) ? maxSize : value);
}
}
public class ResponsePage<T>:List<T>
{
public int currentPage { get; private set; }
public int totalPages { get; private set; }
public int pageSize { get; private set; }
public int totalCount { get; private set; }
public bool hasPrevious => currentPage > 1;
public bool hasNext => currentPage < totalPages;
public ResponsePage(List<T> items,int count,int pageNumber,int pageSize)
{
totalCount = count;
pageSize = pageSize;
currentPage = pageNumber;
totalPages = (int)Math.Ceiling(count / (double)pageSize);
AddRange(items);
}
public static ResponsePage<T> Create(IQueryable<T> source,int pageNumber,int pageSize)
{
var count = source.Count();
var items = source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
return new ResponsePage<T>(items, count, pageNumber, pageSize);
}
}
}