所有API控制器的通用方法分页,过滤所有API [英] Generic Method Pagination for All API Controllers, Filter All APIs

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

问题描述

我正在尝试采用此API并概括分页,因此可以将其用于我的任何API和模型.我将如何进行呢?我在下面放置了现有代码库,并希望适用于所有api及其getmethod.正在研究修改此功能.如果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 = "nancy.davolio@test.com" },  
            new Person() { Name = "Andrew Fuller", DOB = DateTime.Parse("1952-02-19"), Email = "andrew.fuller@test.com" },  
            new Person() { Name = "Janet Leverling", DOB = DateTime.Parse("1963-08-30"), Email = "janet.leverling@test.com" },  
            new Person() { Name = "Margaret Peacock", DOB = DateTime.Parse("1937-09-19"), Email = "margaret.peacock@test.com" },  
            new Person() { Name = "Steven Buchanan", DOB = DateTime.Parse("1955-03-04"), Email = "steven.buchanan@test.com" },  
            new Person() { Name = "Michael Suyama", DOB = DateTime.Parse("1963-07-02"), Email = "michael.suyama@test.com" },  
            new Person() { Name = "Robert King", DOB = DateTime.Parse("1960-05-29"), Email = "robert.king@test.com" },  
            new Person() { Name = "Laura Callahan", DOB = DateTime.Parse("1958-01-09"), Email = "laura.callahan@test.com" },  
            new Person() { Name = "Anne Dodsworth", DOB = DateTime.Parse("1966-01-27"), Email = "anne.dodsworth@test.com" }  
            };  

        // 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,例如author.

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内置了支持此功能的功能,则我接受其他任何策略.

If Microsoft has built into functionality to support this, I am open to Any other strategies.

我会考虑实施

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();
        });
    }
}

Models/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; }
}

Controllers/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 = "nancy.davolio@test.com" },
        new Person() { Name = "Andrew Fuller", DOB = DateTime.Parse("1952-02-19"), Email = "andrew.fuller@test.com" },
        new Person() { Name = "Janet Leverling", DOB = DateTime.Parse("1963-08-30"), Email = "janet.leverling@test.com" },
        new Person() { Name = "Margaret Peacock", DOB = DateTime.Parse("1937-09-19"), Email = "margaret.peacock@test.com" },
        new Person() { Name = "Steven Buchanan", DOB = DateTime.Parse("1955-03-04"), Email = "steven.buchanan@test.com" },
        new Person() { Name = "Michael Suyama", DOB = DateTime.Parse("1963-07-02"), Email = "michael.suyama@test.com" },
        new Person() { Name = "Robert King", DOB = DateTime.Parse("1960-05-29"), Email = "robert.king@test.com" },
        new Person() { Name = "Laura Callahan", DOB = DateTime.Parse("1958-01-09"), Email = "laura.callahan@test.com" },
        new Person() { Name = "Anne Dodsworth", DOB = DateTime.Parse("1966-01-27"), Email = "anne.dodsworth@test.com" }
    };

    // 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆