在 ASP.NET Core 2.1 Web API 中实现分页

Posted

技术标签:

【中文标题】在 ASP.NET Core 2.1 Web API 中实现分页【英文标题】:Implement Pagination in ASP.NET Core 2.1 Web API 【发布时间】:2019-02-19 05:28:50 【问题描述】:

我搜索了,但并没有真正找到关于如何在 ASP.NET WebAPI Core 2.1 应用程序中实现分页逻辑的文章...

我有以下

[Route("api/[controller]")]
[ApiController]
[EnableCors("AllowMyOrigin")]
public class EntriesController : ControllerBase

    private readonly EntriesContext _context;

    public EntriesController(EntriesContext context) 
        _context = context;

        if (_context.Entries.Count() == 0) 
            _context.Entries.Add(new Entry  From = "default", To = "default" );
            _context.SaveChanges();
        
    

    [HttpGet]
    public ActionResult<List<Entry>> GetAll() 
        return _context.Entries.ToList();
    

    [HttpGet("id", Name = "GetEntry")]
    public ActionResult<Entry> GetById(long id) 
        var item = _context.Entries.Find(id);
        if (item == null)  return NotFound(); 
        return item;
    

现在,我希望使用新参数 pagepageSize 对我的条目进行分页。说

/api/entries?pageSize=3&page=2 

我应该通过添加一些 http 参数来使用 GetAll() 方法,还是创建一个新方法?没有pageSize,使用page没有多大意义,我该如何管理?

【问题讨论】:

【参考方案1】:

首先,您可以将pageSize 的值默认为某个值:

[HttpGet]
public ActionResult<List<Entry>> GetAll(int? page = null, int? pageSize = 10) 

    if (!page.HasValue) 
        return _context.Entries.ToList();
    

    // do you pagination here

但你也可以看看OData,这似乎是你的情况。它将允许您使用 http 参数查询您的数据,例如:/api/Entires?$skip=5&amp;$top=5

【讨论】:

OData 不可用,因为我了解 .NET Core 2.1 ?它似乎在 2.1 中被破坏了...github.com/OData/WebApi/issues/1447 @Serge 它应该可以正常工作,尽管它可能有一些问题。还提供问题已关闭 我建议不要使用 OData。许多大公司已经放弃了它的使用,例如 Netflix。甚至微软也在质疑它的未来。它是一项真正难以取得进展的专有技术。 Tx,您知道在 ASP.NET Core(带有 EF Core)和基于 .NET Standard 的客户端(Uno 平台)中是否有一个像样的 OData 服务器端 + 客户端? 【参考方案2】:

有一些库,例如X.PagedList 可以使用。坦率地说,分页非常简单,所以你甚至可能不需要它。您只需要知道页码、页面大小和结果总数。页码显然来自请求,如果您希望它可以自定义,或者您可以对其进行硬编码,页面大小也可以。

public ActionResult<List<Entry>> GetAll(int page = 1, int size = 10)

然后,您可以使用SkipTake 来获取特定页面的数据:

var query = _context.Entries;
var entries = await query.Skip((page - 1) * size).Take(size).ToListAsync();
var count = await query.CountAsync();

那么,您只需要知道总页数,可以通过以下方式简单计算:

var totalPages = (int)Math.Ceil(count / (float)size);

由此,您可以计算出您需要的任何其他内容,即:

var firstPage = 1; // obviously
var lastPage = totalPages;
var prevPage = page > firstPage ? page - 1 : firstPage;
var nextPage = page < lastPage ? page + 1 : lastPage;

【讨论】:

我认为你可以用await Task.WhenAll(people, count); 等待entriescount 而不是依次等待? @koral,DbContext 不是线程安全的,所以你会得到一个异常【参考方案3】:

我刚刚为 ASP.NET Core Razor 页面创建了一个 PagingTagHelper,只需基本参数即可轻松呈现分页控件,最简单的设置如下所示:

<paging total-records="Model.TotalRecords" page-no="Model.PageNo">
</paging>

您只需要提供总记录和页码即可运行。默认的查询字符串参数是“p”表示页码,“s”表示页面大小,但是,它是可自定义/可本地化的,您可以根据自己的要求更改所有设置。

您可以从 nuget 安装它:

Install-Package LazZiya.TagHelpers -Version 1.0.2

那么你需要将标签助手添加到_ViewImports.cshtml文件中:

@addTagHelper *, LazZiya.TagHelpers

http://ziyad.info/en/articles/21-Paging_TagHelper_for_ASP_NET_Core

更多文档和现场演示即将推出。

【讨论】:

以上是关于在 ASP.NET Core 2.1 Web API 中实现分页的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net core 2.1 Web App 无法在 IIS 上正确呈现

在 ASP.NET Core 2.1 Web 客户端中存储不记名令牌的位置

如何在 asp.net core 2.1 中使用 net.tcp 服务

ASP.NET Core 2.1 MVC - 无法设置从 Web api 响应接收到的 cookie

如何使用 fetch 将 FormData 从 javascript 发送到 ASP.NET Core 2.1 Web API

小5聊Asp.Net Core 2.1基础之部署在IIS上接口请求超时解决方法