AspNetCore ile otomatik filtreler oluşturmak

Özet

 

Uzun bir aradan sonra yeni bir proje ile karşınızdayım. Bugün sizlere AspNetCore projelerinizde herhangi bir ekstra kod yazmadan query string parametrelerini LINQ’e dönüştürmeyi sunacağım.

 

Problem

 

Öncelikle problemin ne olduğunu anlayalım. Standart bir AspNet projemiz olduğunu düşünelim. Elimizde de aşağıdaki gibi Blog nesnemiz var.

 


public class Blog
{
    public string BlogId { get; set; }
    public int CategoryId { get; set; }
    public int Priority { get; set; }
    public bool IsPublished { get; set; }
    public DateTime PublishDate { get; set; }
}

 

Bunu filtrelemek için de şöyle bir DTO olduğunu varsayalım:[en:]And think about you have a DTO to filter Blogs:

 


public class BlogFilterDto
{
    public int CategoryId { get; set; }
    public int Priority { get; set; }
    public bool? IsPublished { get; set; }
    public DateTime PublishDate { get; set; }
}

 

Artık Controller’ımıza gidip, bu objeyi QueryString’den istediğimizi belirtebilir ve bu objeyi filtrelemek için kullanabiliriz

 


    [Route("api/[controller]")]
    [ApiController]
    public class BlogsController : ControllerBase
    {
        [HttpGet]
        public async Task<IActionResult> Get([FromQuery]BlogFilterDto filter)
        {
            var db = new MyDbContext();

            var query = db.Blogs;
            if (filter.CategoryId != null)
                query = query.Where(x => x.CategoryId == filter.CategoryId);

            if (filter.IsPublished != null)
                query = query.Where(x => x.IsPublished == filter.IsPublished);

            if (filter.Priority != null)
                query = query.Where(x => x.Priority == filter.Priority);

            if (filter.PublishDate != null)
                query = query.Where(x => x.PublishDate == filter.PublishDate);

            var list = query.ToList();

            return Ok(list);
        }
    }

 

Bu oldukça zorlayıcı ve manuel efor gerektirirdi.

 

Çözüm

 

Bu işlemi otomatize etmenin pek çok yolu var. Fakat istediğimiz yol Expression üretmek ve doğrudan Entity Framework üzerinden DB sorgusuna dönüşebilmesini sağlamak. Bunu her bir model için ayrı ayrı yapmak yerine, Generic bir şekilde yapan bir kütüphane geliştirdim: AutoFilterer

AutoFilterer

 

Projemize AutoFilterer kütüphanesini NuGet Package olarak ekliyoruz. Daha detaylı kurulum ve kullanım talimatları için GitHub’daki wiki sayfasını ziyaret edebilirsiniz.


 

Daha sonra DTO class’ına gidip FilterBase objesinden miras almasını sağlayın

 


public class BlogFilterDto : FilterBase<Blog>
{
    public int CategoryId { get; set; }
    public int Priority { get; set; }
    public bool? IsPublished { get; set; }
    public DateTime PublishDate { get; set; }
}

 

Ve sonunda Controller’a dönüp bütün o uzun hardcode edilmiş kısmı temizleyip ApplyFilterTo() methodunu çağırabiliriz. Bu otomatik olarak Expression oluşturup, DbSet’teki IQuaryable koleksiyona uygulamış olacak. Daha sonrasında ile tek yapmamız gereken bu sorguyu çalıştırmak.

 

 


    [Route("api/[controller]")]
    [ApiController]
    public class BlogsController : ControllerBase
    {
        // api/Blogs
        // api/Blogs?categoryId=8
        // api/Blogs?categoryId=8&isPublished=False
        // api/Blogs?priority=2

        [HttpGet]
        public async Task<IActionResult> Get([FromQuery]BlogFilterDto filter)
        {
            var db = new MyDbContext();

            var list = filter.ApplyFilterTo(db.Blogs).ToList();

            return Ok(list);
        }
    }

 

Böylelikle çok daha temiz bir kod elde etmiş olduk. Advanced düzey ayarlamaları da DTO üzerinden attribute’ler ile yapmış olacağımızdan, filtreleme sorgularıyla ilgili herhangi bir şey kodun düzenini ve okunabilirliğini bozmamış olacak. Sadece Web API projelerinde değil, MVC projelerinde de kullanılabilir. `Ok()` yerine `View()` return edip, view kısmında filtrelenmiş listeyi kullanabilirsiniz. 

 

İleri Düzey Ayarlamalar

 

Sayfalama, aralık filtreleme, string içerisinde arama gibi özellikler için GitHub sayfasındaki talimatları takip edebilirsiniz.

 

 

label, , , , , ,

Add a Comment

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir