مقدمه
اگر با Apiها کار کرده باشید احتمالاً با این چالش که گاهی نیاز است منابعی (Resources) که به کاربر ارسال میشوند مرتب (Sort)، بر اساس درخواست کاربر فیلتر (Filter) و در صفحهبندی (Paging) مشخصی تحویل داده شوند، برخورد کردهاید. این نیاز خصوصاً در پاسخ (Response) با روش GET از استاندارد HTTP مشهود است. در این مطلب به معرفی کتابخانهای میپردازیم که با استفاده از آن میتوان عملیات فوق را پیادهسازی نمود. Sieve یک چارچوب (Framework) ساده، تمیز و قابل توسعه برای NET Core. است. در زمان نگارش این مقاله ویرایش ۲.۱.۳ از این کتابخانه در دسترس است و همانگونه که اشاره شد، این کتابخانه منبع باز (Open Source) بوده و میتوانید آن را از مخزن گیتهاب در این پیوند دریافت نمایید.// Post public int Id { get; set; } public string Title { get; set; } public int LikeCount { get; set; } public int CommentCount { get; set; } public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
۱. نصب کتابخانه
۲. اضافه کردن سرویس
services.AddScoped<SieveProcessor>();
۳. تعیین ویژگیهایی از کلاس برای اعمال مرتبسازی و فیلتر
۱.۳. از طریق اضافه کردن صفت (Attribute) به ویژگیها
// Post public int Id { get; set; } [Sieve(CanFilter = true, CanSort = true)] public string Title { get; set; } [Sieve(CanFilter = true, CanSort = true)] public int LikeCount { get; set; } [Sieve(CanFilter = true, CanSort = true)] public int CommentCount { get; set; } [Sieve(CanFilter = true, CanSort = true, Name = "created")] public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
۲.۳. از طریق Fluent API
برای استفاده از این روش، ابتدا کلاسی را ایجاد و از کلاس SieveProcessor مشتق کنید. سپس تابع MapProperties موجود در کلاس والد را override کنید.// ApplicationSieveProcessor public class ApplicationSieveProcessor : SieveProcessor { public ApplicationSieveProcessor( IOptions<SieveOptions> options, ISieveCustomSortMethods customSortMethods, ISieveCustomFilterMethods customFilterMethods) : base(options, customSortMethods, customFilterMethods) { } protected override SievePropertyMapper MapProperties(SievePropertyMapper mapper) { mapper.Property<Post>(p => p.Title) .CanFilter() .HasName("a_different_query_name_here"); mapper.Property<Post>(p => p.CommentCount) .CanSort(); mapper.Property<Post>(p => p.DateCreated) .CanSort() .CanFilter() .HasName("created_on"); return mapper; } }
services.AddScoped<ISieveProcessor, ApplicationSieveProcessor>();
۴. دریافت پرسوجوهای (Queries) مرتب/فیلتر/صفحهبندی با اضافه کردن SieveModel به کنترلر (Controller)
[HttpGet] public JsonResult GetPosts(SieveModel sieveModel) { var result = _dbContext.Posts; result = _sieveProcessor.Apply(sieveModel, result); return Json(result.ToList()); }
۵. ارسال درخواست
GET /GetPosts ?sorts= LikeCount,CommentCount,-created // sort by likes, then comments, then descendingly by date created &filters= LikeCount>10,Title@=awesome title, // filter to posts with more than 10 likes, and a title that contains the phrase "awesome title" &page= 1 // get the first page... &pageSize= 10 // ...which contains 10 posts
- filters: دستورالعملهای جدا شده توسط کاما (,) به صورت {Name}{Operator}{Value} که در آن:
- {Name} نام ویژگیای است که صفت Sieve بر روی آن تعریف شده و یا نام سفارشیای است که کاربر تعیین کرده است.
- همچنین میتوانید بیش از یک نام (برای یای منطقی (OR)) در درون جفت پرانتز باز و بسته و جداکننده یای منطقی (|) داشته باشید. برای مثال: LikeCount|CommentCount)>10) مشخص میکند مقدار LikeCount و یا CommentCount بیش از ۱۰ باشد.
- {Operator} یکی از عملگرهای ممکن است.
- {Value} مقداری است که در عمل فیلتر مورد استفاده قرار میگیرد.
- page: شماره صفحهای است که برگشت داده میشود.
- pageSize: تعداد مواردی است که در هر صفحه برگردانده خواهد شد.
۶. عملگرها (Operators)
عملگر | توضیحات | عملگر | توضیحات |
== | برابر | =@ | شامل |
=! | مخالف | =_ | شروع شود با |
< | بزرگتر | *=@ | شامل (حساس به حروف)* |
> | کوچکتر | *=_ | شروع شود با (حساس به حروف) |
=< | بزرگتر مساوی | *== | برابر (حساس به حروف) |
=> | کوچکتر مساوی | |
۷. پیکربندی
{ "Sieve": { "CaseSensitive": "boolean: should property names be case-sensitive? Defaults to false", "DefaultPageSize": "int number: optional number to fallback to when no page argument is given. Set <=0 to disable paging if no pageSize is specified (default).", "MaxPageSize": "int number: maximum allowed page size. Set <=0 to make infinite (default)", "ThrowExceptions": "boolean: should Sieve throw exceptions instead of silently failing? Defaults to false" } }
services.Configure<SieveOptions>(Configuration.GetSection("Sieve"));