控制器的通用方法分页

控制器的通用方法分页

本文介绍了所有 API 控制器的通用方法分页,过滤所有 API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试采用此 API 并概括分页,因此它可以用于我的任何 API 和模型.我将如何进行?我将现有的代码库放在下面,并希望适用于所有 apis 及其 getmethods.正在研究修改这个功能.如果 Microsoft 已内置支持此功能的功能,我愿意接受任何其他策略.

I am trying to take this API and generalize Pagination, so it can be used for Any of my APIs and Models. How would I conduct this? I placed existing code base below, and want to have applicable to all apis and their getmethods. Researching to modify this function. If Microsoft has built into functionality to support this, I am open to Any other strategies.

来自资源(现有代码仅可用于 1 类 API):

https://dejanstojanovic.net/aspnet/2019/january/filtering-and-paging-in-aspnet-core-web-api/

背景:

我们准备了很多 Get API,现在想要对所有 200 多个 api 提供分页支持.(我后来进入这个项目)没有手动更新/重新编码所有内容,是否有一种自动方法可以使用上面的资源链接或其他想法将路由/分页应用于我们的端点客户的所有 API?寻求过滤所有 API 的方法.

We prepared many Get APIs, and now want pagination support for all 200+ apis. (I came into the project later) Without manually update/recoding everything, is there a automatic method to apply routing/pagination to all APIs for our end point customers using maybe resource link above or other ideas? Seeking way to filter all APIs.

public ActionResult<PagedCollectionResponse<Person>> Get([FromQuery] SampleFilterModel filter)


/api/Persons?Page=2&Limit=3

/api/Inventory?Page=2&Limit=3

/api/Product?Page=2&Limit=3
/api/Product/GetAll/Page=2&Limit=4
/api/Product/GetByProductCategory/7/Page=2&Limit=4
/api/Product/GetByVendorId/2/Page=2&Limit=4
/api/Product/GetByProductLocation/US/CA/Page=2&Limit=4

代码:

namespace Sample.Web.Api.Models
{
    public abstract class FilterModelBase:ICloneable
    {
        public int Page { get; set; }
        public int Limit { get; set; }
        public FilterModelBase()
        {
            this.Page = 1;
            this.Limit = 100;
        }
        public abstract object Clone();
    }
}

public class SampleFilterModel:FilterModelBase
{
    public string Term { get; set; }
    public SampleFilterModel():base()
    {
        this.Limit = 3;
    }
    public override object Clone()
    {
        var jsonString = JsonConvert.SerializeObject(this);
        return JsonConvert.DeserializeObject(jsonString,this.GetType());
    }
}

namespace Sample.Web.Api.Models
{
    public class PagedCollectionResponse<T> where T:class
    {
        public IEnumerable<T> Items { get; set; }
        public Uri NextPage { get; set; }
        public Uri PreviousPage { get; set; }
    }
}

namespace Sample.Web.Api.Models
{
    public class Person
    {
        public String Name { get; set; }
        public DateTime DOB { get; set; }
        public String Email { get; set; }
    }
}

namespace Sample.Web.Api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class PersonsController : ControllerBase
    {

        IEnumerable<Person> persons = new List<Person>() {
            new Person() { Name = "Nancy Davolio", DOB = DateTime.Parse("1948-12-08"), Email = "[email protected]" },
            new Person() { Name = "Andrew Fuller", DOB = DateTime.Parse("1952-02-19"), Email = "[email protected]" },
            new Person() { Name = "Janet Leverling", DOB = DateTime.Parse("1963-08-30"), Email = "[email protected]" },
            new Person() { Name = "Margaret Peacock", DOB = DateTime.Parse("1937-09-19"), Email = "[email protected]" },
            new Person() { Name = "Steven Buchanan", DOB = DateTime.Parse("1955-03-04"), Email = "[email protected]" },
            new Person() { Name = "Michael Suyama", DOB = DateTime.Parse("1963-07-02"), Email = "[email protected]" },
            new Person() { Name = "Robert King", DOB = DateTime.Parse("1960-05-29"), Email = "[email protected]" },
            new Person() { Name = "Laura Callahan", DOB = DateTime.Parse("1958-01-09"), Email = "[email protected]" },
            new Person() { Name = "Anne Dodsworth", DOB = DateTime.Parse("1966-01-27"), Email = "[email protected]" }
            };

        // GET api/values
        [HttpGet]
        public ActionResult<PagedCollectionResponse<Person>> Get([FromQuery] SampleFilterModel filter)
        {

            //Filtering logic
            Func<SampleFilterModel, IEnumerable<Person>> filterData = (filterModel) =>
            {
                return persons.Where(p => p.Name.StartsWith(filterModel.Term ?? String.Empty, StringComparison.InvariantCultureIgnoreCase))
                .Skip((filterModel.Page-1) * filter.Limit)
                .Take(filterModel.Limit);
            };

            //Get the data for the current page
            var result = new PagedCollectionResponse<Person>();
            result.Items = filterData(filter);

            //Get next page URL string
            SampleFilterModel nextFilter = filter.Clone() as SampleFilterModel;
            nextFilter.Page += 1;
            String nextUrl = filterData(nextFilter).Count() <= 0 ? null : this.Url.Action("Get", null, nextFilter, Request.Scheme);

            //Get previous page URL string
            SampleFilterModel previousFilter = filter.Clone() as SampleFilterModel;
            previousFilter.Page -= 1;
            String previousUrl = previousFilter.Page <= 0 ? null : this.Url.Action("Get", null, previousFilter, Request.Scheme);

            result.NextPage = !String.IsNullOrWhiteSpace(nextUrl) ? new Uri(nextUrl) : null;
            result.PreviousPage = !String.IsNullOrWhiteSpace(previousUrl) ? new Uri(previousUrl) : null;

            return result;

        }
    }
}

注意:

需要根据资源将其扩展到 API 级别.我们知道它可以在业务存储库方法中完成,但想要推广到所有控制器 API,例如上面的作者.

Need to Extend it to the API level as per resource. We know it can be done in business repository method, but want to generalize for all Controller APIs like author from above .

推荐答案

回应:

如果 Microsoft 已内置支持此功能的功能,我愿意接受任何其他策略.

我会考虑实施 OData v4 如果这是一个选项.然后,您可以使用 $top$skip 查询参数跨所有 API 标准化分页.

I would look into implementing OData v4 if that's an option. You can then standardize pagination across all your APIs using $top and $skip query parameters.

所以粗略地你会想要做这样的事情:

So roughly you would want to do something like this:

在项目上安装 Microsoft.AspNetCore.OData Nuget 包.有关这些功能的更多文档可以在 OData WebApi 更改日志.

Install the Microsoft.AspNetCore.OData Nuget package on the project. More documentation about the features can be found in the OData WebApi changelog.

然后修改如下所示的代码以开始使用 OData 的基本实现.

Then modify the code as shown below to get started with a basic implementation of OData.

Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        // Configure the use of OData
        services.AddOData();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        // Configure MVC to support OData routes
        app.UseMvc(config =>
        {
            config.EnableDependencyInjection();
            config.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
        });
    }
}

模型/Person.cs

// Set the MaxTop value accordingly
[Page(MaxTop = 100)]
public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
    public DateTime DOB { get; set; }
}

控制器/PersonsController.cs

[Route("api/[controller]")]
[ApiController]
public class PersonsController : ControllerBase
{
    private readonly IEnumerable<Person> persons = new List<Person>()
    {
        new Person() { Name = "Nancy Davolio", DOB = DateTime.Parse("1948-12-08"), Email = "[email protected]" },
        new Person() { Name = "Andrew Fuller", DOB = DateTime.Parse("1952-02-19"), Email = "[email protected]" },
        new Person() { Name = "Janet Leverling", DOB = DateTime.Parse("1963-08-30"), Email = "[email protected]" },
        new Person() { Name = "Margaret Peacock", DOB = DateTime.Parse("1937-09-19"), Email = "[email protected]" },
        new Person() { Name = "Steven Buchanan", DOB = DateTime.Parse("1955-03-04"), Email = "[email protected]" },
        new Person() { Name = "Michael Suyama", DOB = DateTime.Parse("1963-07-02"), Email = "[email protected]" },
        new Person() { Name = "Robert King", DOB = DateTime.Parse("1960-05-29"), Email = "[email protected]" },
        new Person() { Name = "Laura Callahan", DOB = DateTime.Parse("1958-01-09"), Email = "[email protected]" },
        new Person() { Name = "Anne Dodsworth", DOB = DateTime.Parse("1966-01-27"), Email = "[email protected]" }
    };

    // GET: api/Persons
    [HttpGet]
    [EnableQuery]
    public IEnumerable<Person> Get() => persons;
}

然后在浏览器中根据 OData 规范执行查询.例如:

Then in the browser you execute queries in accordance with the OData spec. For example:

GET /api/Persons?$skip=1&$top=3

这篇关于所有 API 控制器的通用方法分页,过滤所有 API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 02:19