OData Davranış Modellemesi ve Attributeları

Merhaba,

OData protokolüne dair önceden kaleme almış olduğumuz makalelerimizden görüldüğü üzere, OData; controllerların yönetimini ele almakta ve belirli varsayılan standartlar üzerine yapılanmayı inşa etmektedir. İşte bu içeriğimizde OData’nın varsayımsal standartlarını inceleyecek ve bir nebze özelleştirme dokunuşlarında bulunacağız.

OData Controller Yapılanması

OData protokolü üzerinden sorgulama yapılabilecek bir controller modeli için aşağıdaki örneği ele alırsak eğer;

    public class PersonelController : ODataController
    {
        NorthwindContext _northwindContext;
        public PersonelController(NorthwindContext northwindContext)
        {
            _northwindContext = northwindContext;
        }
        [EnableQuery]
        public IActionResult Get()
        {
            return Ok(_northwindContext.Personeller);
        }
    }

görüldüğü üzere, ilgili controller sınıfımız standart API yapılanmasındaki gibi ne ‘ApiController’ veya ‘Route’ attributeları tarafından işaretlenmekte ne de ‘ControllerBase’ sınıfında türemektedir. Tabi burada ele almasakta uygulamaya entegre edilen protokol yapılanmasının konfigürasyonlarında bu controller ‘ODataConventionModelBuilder’ nesnesine ‘EntitySet’ olarak tanımlanmakta ve Edm(Entity Data Model) olarak ilgili controller’ın tüm yönetimi OData protokolüne devredilmektedir. implemantasyon için gerekli konfigürasyon temellerini ele aldığımız Asp.NET Core Web API Uygulamasına OData Implementasyonu başlıklı makaleyi inceleyebilirsiniz.

İşte bu devir neticesinde artık OData ilgili controller’da ki tanımlamaları belirli bir standart çerçevesindeki varsayımlarla değerlendirmekte ve davranışını bu varsayımlara göre göstermektedir.

Nedir bu varsayımlar?
URL üzerinden yapılan sorgulamada bir ‘GET’ isteği gönderilecekse eğer bu isteği karşılayacak metot isminin ya ‘Get’ ya da ‘Get{controller_name}’ formatında olması gerekmektedir. Aksi taktirde isteği karşılayacak farklı isimde tanımlanmış bir metot işlevsellik göstermeyecektir.

Benzer şekilde ‘id’ bazlı sorgulamaların yapılacağı durumlarda ilgili ‘Get’ metodunun aşağıdaki gibi isimlendirilmiş olması gerekmektedir.

        [EnableQuery]
        public IActionResult Get([FromODataUri]int key)
        {
            return Ok(_northwindContext.Personeller.Where(p => p.PersonelId == key));
        }

ya da

        [EnableQuery]
        public IActionResult GetPersonel([FromODataUri]int key)
        {
            return Ok(_northwindContext.Personeller.Where(p => p.PersonelId == key));
        }

Görüldüğü üzere ‘id’ değerini karşılayacak olan parametre birebir ‘int key’ şeklinde tanımlanmalı ve ‘FromODataUri’ attribute’u ile işaretlenmelidir. ‘int key’ parametresi ‘int id’ şeklinde tanımlandığında bile ilgili metot hiçbir sorgulamada yine işlevsellik göstermeyecektir.

Yukarıdaki gibi ‘id’ bazlı sorgulama fonksiyonlarına istek gönderebilmek için aşağıdaki gibi url oluşturulması yeterlidir.

1 id değerine sahip olan personeli getirir.
https://localhost:5001/odata/personel(1)

9 id değerine sahip olan personelin adını, soyadını ve yaptığı tüm satışların; satış id, satış tarihi ve adedini getirir.
https://localhost:5001/odata/personel(9)?$select=adi, soyadi&$expand=satislar($select=satisid, satistarihi;$count=true)

ODataRoute Attribute’u

Peki bu varsayımları nasıl özelleştirebiliyoruz?
Metot yahut parametre isimlerini özelleştirebilmek için ‘ODataRoute’ attribute’u kullanılır. Şöyle ki;

        [ODataRoute("personel")]
        [EnableQuery]
        public IActionResult GetTumPersoneller()
        {
            return Ok(_northwindContext.Personeller);
        }

ya da

        [EnableQuery]
        [ODataRoute("personel({id})")]
        public IActionResult GetIdyeGorePersonel([FromODataUri] int id)
        {
            return Ok(_northwindContext.Personeller.Where(p => p.PersonelId == id));
        }

şeklinde kullanılabilmektedir. Burada ‘ODataRoute’ attribute’unda belirtilen ‘personel’ değerinin birebir controller ismiyle aynı olduğuna ve ‘({id})’ değerininde parametredekiyle isim olarak eşleştiğine dikkatinizi çekerim. Tabi burada bir hususa daha değinmek istiyorum. O da bu metotların isimlerinin ‘Get…’ ile başlama gereksinimidir. Eğer ki ‘Get…’ ön ekiyle başlamazlarsa sorgulama neticesinde bu metotlar işlevsellik göstermeyeceklerdir.

ODataRoutePrefix Attribute’u

Custom isimlendirilmiş action metotları ‘ODataRoute’ attribute’u ile bildirirken daima controller ismini bildirmemiz gerekmektedir. Haliyle bu durum tüm actionlarda gerçekleşince aşağıdaki gibi tekrar eden bir yapılanma karşımıza çıkacaktır.

    public class PersonelController : ODataController
    {
        NorthwindContext _northwindContext;
        .
        .
        .
        [ODataRoute("personel")]
        [EnableQuery]
        public IActionResult GetTumPersoneller()
        {
            return Ok(_northwindContext.Personeller);
        }

        [EnableQuery]
        [ODataRoute("personel({id})")]
        public IActionResult GetIdyeGorePersonel([FromODataUri] int id)
        {
            return Ok(_northwindContext.Personeller.Where(p => p.PersonelId == id));
        }
    }

İşte bu tekrarı engellemek için controller seviyesinde ‘ODataRoutePrefix’ attribute’unu kullanabilir ve tüm ‘ODataRoute’ attribute’larında tekrar tekrar controller ismini yazmaktan kurtulunabilir.

    [ODataRoutePrefix("personel")]
    public class PersonelController : ODataController
    {
        NorthwindContext _northwindContext;
        .
        .
        .
        [ODataRoute()]
        [EnableQuery]
        public IActionResult GetTumPersoneller()
        {
            return Ok(_northwindContext.Personeller);
        }

        [EnableQuery]
        [ODataRoute("({id})")]
        public IActionResult GetIdyeGorePersonel([FromODataUri] int id)
        {
            return Ok(_northwindContext.Personeller.Where(p => p.PersonelId == id));
        }
    }

OData Pagination

OData her ne kadar url üzerinden sorgulama yapmamızı sağlayarak API’larımızın yeteneklerini arttırıp biz developerların işlerini kolaylaştırsada, bu kolaylığı gölgede bırakacak başka bir özelliğide bünyesinde barındırmaktadır. Sayfalama… Bunun için action metotları işaretlediğimiz ‘EnableQuery’ attribute’unun ‘PageSize’ parametresine ne kadar veri gelmesi isteniyorsa belirtilmesi yeterlidir. Şöyle ki;

    public class SatisController : ODataController
    {
        NorthwindContext _northwindContext;
        public SatisController(NorthwindContext northwindContext)
        {
            _northwindContext = northwindContext;
        }
        [EnableQuery(PageSize = 5)]
        public IActionResult Get()
        {
            return Ok(_northwindContext.Satislar.ToList());
        }
    }

Bu API’ya aşağıdaki gibi istek gönderildiğinde içerisinde bir sonraki sayfanın linkinide barındıran sonuç döndürülecektir.
https://localhost:5001/odata/satis?$select=satisid,musteriid
OData Davranış Modellemesi ve Attributeları

İşte görüldüğü gibi, bu kadar basit… 😎

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

3 Cevaplar

  1. 22 Mayıs 2020

    […] önceki OData Davranış Modellemesi ve Attributeları başlıklı makalemizde OData protokolünün nasıl bir davranış sergilediğini, action […]

  2. 23 Mayıs 2020

    […] id bazlı sorgulama ile birlikte daha da özelleştirilmiş GET operasyonlarının inşası için şu ve şu makalelere göz atmanızı […]

  3. 27 Mayıs 2020

    […] belirlerken belli kurallar çerçevesinde hareket etmekteyiz. Bu kuralların neler olduğunu OData Davranış Modellemesi ve Attributeları ve OData Custom Route Yapılanması başlıklı makalelerde detaylıca incelemiş bulunmaktayız. […]

Bir cevap yazın

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

*