Asp.Net Core Api ile OData Kullanımı

Hakan Karabulut
Devops Türkiye☁️ 🐧 🐳 ☸️
7 min readMay 16, 2020

Bu makalede OData hakkında bilgi verip, dotnet projesinde uygulaması ile ilgili örnekleme yapmaya çalışacağım.

OData Nedir?

Open Data Protocol olarak da isimlendirebileceğimiz OData, veri kaynaklarını REST url üzerinden sorgulama protokolüdür. Microsoft tarafından 2007 yılında geliştirilmeye başlanmıştır. Api uygulamalarında kullanılmakatadır.

OData ile yapacağınız sorguları client tarafına bırakarak, complex ya da tailored endpointler geliştirme maliyetinden kurtulabilirsiniz.

OData action dönüş tipinin IQueryable olması daha performanslı sorgulamalar yapmamızı sağlar.

Projeye Dahil Edilmesi

Nuget üzerinden paket projeye dahil edilir.

ConfigureServices kısmında aşağıdaki gibi servis katmanına eklememizi yapıyoruz.

Middleware olarak ekleme için Configure içinde aşağıdaki gibi bir ayarlama yapılmalıdır.

Yukarıda yazıklarımızı inceleyelim;

  • OData entity’e [EntitySetName]Controller olarak erişim yaptığı için Controller adı olarak ne verdiyeseniz EntitySet içeriğine de böyle bir isimlendirme yapmalısınız.
  • Birinci “odata” routeName olarak veriyoruz.
  • İkinci “odata” ise www.your_awesome_domain.com/odata/entityName sorgulama yapacağımız prefix’i tanımlamak için veriyoruz.
  • builder.GetEdmModel() ise EntityDataModel’in kısaltmasıdır. Model’in property’lerine ve navigation property’lerine erişim için kullanılır. Database üzerinden alınan sorguları entity model’ine dönüştürür.

Şimdi Controller’ları oluşturmaya başlayabiliriz.

Bir controller’in OData ile ilişkisini kurmak için ODataController’dan türetilmesi yeterlidir. Dikkat ettiyseniz ApiController ve Route ile ilgili tanımlamalar yer almıyor, OData bizim yerimize bu işlemleri üstleniyor.

Odata’nın kullanımı için Controller bazında bir kaç şeye daha dikkat etmemiz gerekmektedir.

  • OData Controller içinde method isimlendirmesi Get() ya da GetCities() (entity’nin çoğul hali) şeklinde olmalıdır.
  • OData Controller’a sorgulama özelliğini kazandırmak için method üzerine [EnableQuery] attribute konulmalıdır.

OData’nın projemize dahil edilmesi bu kadar kolay =)

OData Metadata ($metadata)

OData’nın kullandığı entity’ler hakkında bilgi içeren bir nevi dökümantasyonuna erişmek için www.your_awesome_domain.com/odata/$metadata yazmanız yeterlidir.

OData ile Swagger birlikte kullanmanız pek mümkün değil, onun için Metadata dökümantasyon ihtiyacını karşılıyor.

OData ile sorgulama nasıl yapılır bunu incelemeye başlayabiliriz artık.

OData Query Options

Query Options’lar server üzerinden dönecek data miktarını kontrol etmek için kullandığımız seçeneklerdir. Üç parça olarak inceleyebiliriz. Birinci kısım base url (your_awesome_url/odata), ikinci kısım resource (cities) yani controller, üçüncü kısım ise filtre yapacağımız alan ($select=Name) olarak sınıflandırılabilir.

Query Options yazarken query string key value olduğu için resource sonrasında ? işareti sonrası mutlaka $ işareti kullanılmalıdır.

your_awesome_url/odata/cities?$select=Name,…

Query Options kullandığınızda dönen data her zaman iki parçadan oluşur;

1- “@odata.context”: “http://localhost:5000/odata/$metadata#Cities",

Yukarıdaki yapı ile resource metadata bilgilerini içeren bir bilgi döner.

2- “value”: [] içinde ise data döner. Tek bir değer almaya çalışsanız da value içindeki array içinde geri dönüş olur.

$Select

Entity üzerinden dönecek propertyleri filtrelemek için kullanılır. Hangi propertylere ihtiyacınız varsa onları alma olanağı sunar. Kullanabilmek için Startup içinde şöyle bir ayarlama yapmalıyız.

Filtresiz request ile dönen data
Filtre ile dönen data

$Expand

Sorgulama yaptığımız entity’nin navigation property’si varsa o entity’inin de datalarını alabilme olanağı sunar. $expand yazıp resource entity’nin bağlı bulunduğu navitagion property’i yazarak dataya erişim sağlarız. Tabii bunu da kullanabilmek için aşağıdaki gibi bir ayarlama yapmamız lazım;

your_awesome_url/odata/cities?$expand=country

Resource entity’nin başka bir navigation property’si varsa ve bunu da sorguda almak istiyorsanız “,” ile ayrırarak sorgulama yapabilirsiniz.

your_awesome_url/odata/cities?$expand=country,other_navigation_propery

Expand ile dönen data üzerinde de filtreleme yapabilme olanağımız var. Bunun için parantez içinde $select ile sorgulama yapabilirsiniz

your_awesome_url/odata/cities$expand=country($select=name,alpha2code)

$OrderBy

Entity’nin bir ya da birden fazla property’sine göre sıralama işlemi yapmak için kullanılır. Tabii bunu da kullanabilmek için aşağıdaki gibi bir ayarlama yapmamız lazım;

your_awesome_url/odata/countries?$orderBy=regionId desc

İkinci bir propery ile sıralama yapmak için “,” ile ayırıp desc ya da asc yazarak soruguyu oluşturabiliriz.

your_awesome_url/odata/countries?$orderBy=regionId desc, name asc

$Top

Bir dizinden kaç tane item almak istiyorsak kullanabiliriz.

your_awesome_url/odata/cities?$top=2

$Skip

Adından da anlaşılacağı gibi atlama için kullanılır. Top keyword’ü ile kullanılırsa sayfalama yapabilirsiniz. Endpoint ile iligili bir ayarlama yapmamıza gerek yok, default olarak geliyor.

your_awesome_url/odata/cities?$skip=2

your_awesome_url/odata/cities?$skip=0&$top=3

Birden fazla filtreyi bir arada kullanmak isterseniz & ile filtreleri birleştirebilirsiniz.

$Count

Dönen datanın miktarını belirtir.

your_awesome_url/odata/cities?$count=true

“@odata.count” ile datanın kaç tane olduğunu gösterir.

$Filter

Filtreleme yapmak için kullanılır. Logical operations, arithmetic operations ve functions olmak üzere 3 başlıkta incelemek mümkündür;

Logical Operators

eq : Equal kısaltılmasıdır.

ne : Not Equal kısaltılmasıdır.

gt : Greather than kısaltılmasıdır.

ge : Greather equal kısaltılmasıdır.

lt : Less than kısaltılmasıdır.

le : Less equalkısaltılmasıdır.

your_awesome_url/odata/cities?$filter=name eq ‘İstanbul’

Arithmetic Operators

add : Adding kısaltmasıdır, toplama işlemi için kullanılır.

sub : Subtraction kısaltmasıdır, çıkarma işlemi için kullanılır.

mul : Multiplication kısaltmasıdır, çarpma işlemi için kullanılır.

div : Division kısaltmasıdır, bölmeişlemi için kullanılır.

your_awesome_url/odata/products?$filter=stock add 100 eq 500

Stock değeri 500'e eşit olanlara 100 ekler.

Functions

endswith : Herhangi bir string ifadenin sonunun iligili filter ile bitenini getirmek için kullanılır.

startswith : Herhangi bir string ifadenin başlangıcının iligili filter ile başlayanını getirmek için kullanılır.

length : Herhangi bir string ifadenin uzunluğu ile ilgili karşılaştırma yapılabilir.

indexof : Herhangi bir string ifadenin içinde bir harfin hangi index’te yer aldığı ile sorgulama yapmak için kullanılır.

trim : Herhangi bir string ifadenin sağındaki ve solundaki boşluklardan arındırmak için kullanılır.

year : Tarih bilgisi içeren field üzerinden yıl bilgisine göre filtreleme için kullanılır.

month : Tarih bilgisi içeren field üzerinden ay bilgisine göre filtreleme için kullanılır.

day : Tarih bilgisi içeren field üzerinden gün bilgisine göre filtreleme için kullanılır.

your_awesome_url/odata/cities?$filter=year(CreatedDate) eq 2020

OData/Attribute

OData’nın controller düzeyinde isimlendirme kurallarından daha önce bahsetmiştik. Şimdi biraz daha fazla bu konuları inceleyelim, istersek custom route ve isimlendirmeleri nasıl yapabileceğimize bakalım.

Id alanı ile sorgulama yapmak istersek default olarak şöyle olmalıdır;

your_awesome_url/odata/cities(40)

Şimdiye kadar gördüğümüz tüm filtreleme yöntemlerini de sorguya dahil edebiliriz.

ODataRoute

Custom isimlendirme yapmak istersek OData’ya kullanıdğımız ismi ODataRoute attribute ile bildiriyoruz.

ODataRoutePrefix

ODataRoute ile custom isimlendirme yaparken daima [ODataRoute(“cities({itemId})”)] controller isimlendirmesi yapmamız gerekiyor. Bu tekrarı engellemek için Controller class’ının başına [ODataRoutePrefix(“cities”)] eklemesi yaparsak tekrar tekrar Controller ismini yazmamıza gerek kalmaz, [ODataRoute(“({itemId})”)] olarak yazabiliriz.

OData Pagination

OData ile sayfalama yapmak gerçekten çok kolay =)

[EnableQuery(PageSize = 10)]

EnableQuery attribute içine kaç item yer almasını istiyorsanız PageSize ile belitmeniz yeterli.

your_awesome_url/odata/cities

Dikkat ederseniz gelen data dışında

“@odata.nextLink”: “http://localhost:5000/odata/cities?$skip=10"

gibi bir link var. Buna tıkladığınızda bir sonraki sayfayı gösterecektir.

OData Action/Function

Bir method içinde complex type ya da fazla parametre alması durumunda Action ya da Function kullanılabilir. İkisi arasındaki fark; Action Post ile sorgulama için kullanılır. Function ise Get sorgulaması ile kullanılır. Action ya da Function kullanmak için tanımlama yaptığınız isimle bire bir aynı endpointinizin olması gerekmektedir.

OData Action (No Parameter)

Kullanmış olduğum endpointler için custom bir method yazacağım. Geriye string bir data dönecek. Bunun için County modelini kullanacağım ve geriye ülke adı ve sembolü dönen basit bir result dönecek. Startup içinde aşağıdaki gibi bir tanımlama yapıyorum;

Endpoint olarak belirtmiş olduğum isimlendirmeyi kullanmam lazım. Action yazdığımız için Post ile istek yapmamız gerekmektedir.

OData Action (With Parameter)

OData Action Multiple Parameter

OData Action ComplexType

Basit bir model oluşturuyorum;

OData Function (No Parameter)

OData Function (With Parameter)

OData UnBound Function/Action

OData, bir entity’e bağlı olmadan da Function ya da Action oluşturmamıza olanak sağlamaktadır.

Son olarak şunu hatırlatalım, endpoint bazında OData ile ilgili engellemeler ya da izinler vermek isterseniz EnableQuery attribute içinden bunları yapma olanağınız vardır. Attribute’ü karıştırdığınızda çok rahatlıkla görebilirsiniz diye teker teker izah etmeye gerek duymadım.

Ayrıca entity düzeyinde de $select, $filter vb engellemeler ya da izinler verme olanağınız bulunmaktadır.

OData’nın Swagger ile birlikte kullanımı olmadığı için ben sadece tüm datayı listelediğim (GetAll gibi) ya da id ile tek bir datayı gösterdiğim (GetById gibi) endpointlerde kullanıyorum. Bu endpointlerde de fazlasıyla iş çıkardığı için tercih sebebim oluyor.

Ayrıca piyasadaki rakibi GraphQL ile kıyaslandığında çok daha kısa sürede öğrenilen ve uygulamaya geçirmesi çok çok daha kolay olduğu için tercih ediyorum.

--

--