Web API Cross-Domain & OData & GET,GET(ID),UPDATE

Web API bir çeşit webservisidir. Ama en büyük farkı HTTP tabanlı olmasıdır.Buda platformadan, browserdan ve dilden bağımsız olarak her yerde kullanılabilmesini sağlamıştır.
Bir mobile uygulamada ilgili productları verirken, bir televizyon uygulamasında o günkü akışı verebilmektedir.İstemcilere HTTP protokolünün Post, Put, Get, Delete gibi standart methodlara karşılık vermektedir.

Farkıl formatlarda xml,json gibi istemcilere cevap verebilmesi, ayrıca OData(Open Data Protocol) desteği sayesinde,  URL bazlı parametreler ile filitreleme yapabilmesi Web Api’in bize getirdiği yeni özelliklerden birkaçıdır. Eskiden Restful dediğimiz servislerden Javascript ile cross domaine düşmeden data çekmek çok meşakatli ve yorucu bir işti. Bu işlem web api ile çok basitleşmiştir.Çünkü REST baseddir.

hf-adapter

Bazen database’in tamamını dış bir sisteme açmak istemeyiz. Adapter Design Pattern’de olduğu gibi, görülmesine izin verdiğimiz kadarını dış dünyaya açabiliriz. Bunun için tek yapmamız gereken Web API’nin döndüreceği  datamodel’e sınırlar koymaktan başka birşey değildir.

Şimdi isterseniz örneğimize geçelim. Öncelikle data modelelmiz olan product’ı aşşağıda görüldüğü gibi oluşturalım.

Models/product.cs

 

Aşşağıda controller’ımuzu ApiController’dan türettik.Ve önceden yarattığımız data modelimizi manuel olarak doldurduk.Dikkat ederseniz GetAllProduct() methodunun üstüne [Queryable] attribute’u eklenmiştir.Amaç OData(Open Data Protocol) kullanılarak Url üzerinden filter yapmaktır.

OData’nun kullanılabilmesi için NuGet’den alttaki dosyanın indirilmesi gerekmektedir.

odataPNG

Manuel doldurduğumuz aşşağıdaki Product Listemizden dışarıya servis yaratırken Category’sini paylaşmak istemediğimizi planlıyalım. Bunu için viewmodelimizi doldururken category’i göz ardı ettik.Ve sonunda modelimizi model.AsQueryable() olarak döndürdük.Bir de performance amaçlı cache kullandık.Update işlemlerini göz önüne alarak 30 dakikalık bir cache oluşturduk.

WebAPI servisinin farklı domainlerde çalışması için cross domin olması gerekmektedir.Bunun için NuGet’in Library Package Manager dan Package Manager Console’a :

Capture yazılır.

Tabi henüz işimiz bitmedi.Projemizdeki /App_Start/WebApi.config içine aşşağıdaki kod satırı eklenmesi gerekmektedir.

config.EnableCors();

Ayrıca ProductsController class’ının  başına ya da kullanılacak tüm methodların başına tek tek aşşağıda görülen attribute’un eklenmesi gerekir.

Bir de ID parametresi ile Get işelmi yapıldığı zamanki çağrılacak methodu yazalım.Gerçi istersek Odata Url $filter‘ile de bunu yapabiliriz.Arada tabi fark var:)

Aşşağıdaki örnekte görüldüğü gibi Linq Categori propertysini çıkarıp istenen ID’li Product’ı döndürelim.Burada yine cache kullanılmıştır.İlgili data gene 30dakkalık cache üzerinden alınmıştır.

Yukarıdaki örnekte bunu neden yapmamış diyen arkadaşlar için aşşağıda linq extension kullandım:) Bu arada merak edenler için Linq üzerine derinlemesine ayrı bir makale yazıcam.

Şimdilik projemizi bu hali ile derleyip azure üzerine publish yapalım ki cross domain özelliğini de test edebilelim.

azurepub

Şimdilik url’den bir request atalım: http://webapiblog.azurewebsites.net/api/products

Mesela her sayfada 2 kayıt olmak üzere 5.sayfa gösterilmek istenirse alttaki gibi bir url query yazılabilir.

http://webapiblog.azurewebsites.net/api/products?$top=2&$skip=5

Price 100 den aşşa olanlar için aşşağıdaki gibi bir url query yazılabilir:

http://webapiblog.azurewebsites.net/api/products?$filter=Price le 100

İsmi Cam ile başlıyan ürünler için aşşağıdaki gibi bir url query yazılabilir:

http://webapiblog.azurewebsites.net/api/products?xml=true&$filter=startswith(Name,’Cam’)

İsminde ‘or’ geçenler için aşşağıdaki gibi bir url query yazılabilir:

http://webapiblog.azurewebsites.net/api/products?xml=true&$filter=substringof(‘or’,Name)

İsme göre tersten sıralama için aşşağıdaki gibi bir url query yazılabilir:

http://webapiblog.azurewebsites.net/api/products?xml=true&$orderby=Name desc

Peki parametreye göre result’ı xml yada json nasıl yapabiliriz?

Global.asax’a aşşağıdaki kodu yazmamız yeterlidir:

Yukarıdaki kodlar eklendiğinde, header tipini url’de xml=true parametresi bulunursa xml, yok ise json formatı oluşturularak sonuç döndürülür.

Şimdi gelelim 2 farklı sorgu biçimine. Ilki aşağıdaki gibidir:

http://webapiblog.azurewebsites.net/api/products?xml=true&$filter=ID eq 8

Diğeri:

http://webapiblog.azurewebsites.net/api/products/8?xml=true

Bu ikisi arasındaki fark nedir? İkiside aynı ID’si 8 olan ürünü döner. Esas fark biri yani odata filter kullanılan;  tüm kayıtı önce çeker, sonra ID=8 olan resultı getirir ve Get() methodunu kullanır.

Diğer sadece ID’si 8 olan ürünü çeker.Ve Get(ID) methodunu kullanır.

Buraya kadar olan kısmı test amaçlı olarak bir test mvc projesi açalım.

Index sayfamıza alttaki gibi product namelerin geleceği bir dropbox ve detay bilgisinin dolacağı 4 textbox getirelim.

Örnek Ekran Url’i (İptal): http://testwebapiblogs.azurewebsites.net/

Aşşağıda görüldüğü gibi webAPI’ile çekilen ürün isimleri ilgili dropbox’a doldurulmuştur. Bu da bize cross domain’i aştığımızı göstermektedir.

drop

Aşşağıdaki scirpt’de dropbox’dan bir ürün seçildiği zaman detayı getirilmiştir:

result

Yukarıda görüldüğü üzere sonucu 2 farklı şekilde çekilmiştir.1.si odata filter kullanarak.2. side Get(int ID) methoduna yönelmek.Tabiki performans için Get(ID) methodu çok daha verimlidir.Çünkü tek bir kayıt çekmektedir. Odata url filter’da, önce tüm kayıt çekilir sonra ID değerine göre filter yapılır.

Dikkat edilirse Category bilgisi paylaşılmak istenmiyordu. Burada da görüldüğü üzere category bilgisi gelmemiştir.

Şimdi biraz’da güncellme üzerine bir örnek yapalım.Amaç Name veya Price için yapılan değişikliği 30’dakkalık cache’e yansıtmak.Önce gerekli WebAPI  kodlarını oluşturalım.

Aşşağıda görüldüğü gibi değişen product’ın ID’sinden eski product çekilir. Çekilen bu product cache içindeki List<Product>’dan çıkarılır ve yerine değişen bu yeni product item konur.En sonunda da cache güncellenir ve işlem bitince kaydedilip ilgili mesaj döndürülür.

 

Aşşağıda görüldüğü gibi bir de Index view’ı inceliyelim.Kaydet diye bir button koyulmuştur.

Değişen product değerlerini tekrardan doldurulduktan sonra WepAPI ile data json olarak post edildi. İşlem başarıldığında productları listeleyen dropdownlist sıfırlanıp tekrardan servis yardımı ile dolduruldu.Ve geri kalan tüm alanlar sıfırlandı.

far2

  1. Resimde Far’ın orjinal hali görünmektedir.
  2. İsmi Far yerine Sağ Far olarak değiştirilmiştir.Fiyatı 600 den 545.5’e olarak değiştirilip kaydedildi.
  3. Güncellemeden sonra DropDownList’imizde Far =>Sağ Far olarak gözükmektedir.
  4. Sağ Far seçilince Name=>Sağ Far ve Price=545.5 şeklinde yeni giridiğimiz 30’dakkalık cahce’e kaydedilen değerler gösterilir.

Görüldüğü üzere WebApi birçok platforma, farklı formatlarda servis verebilmektedir.Url üzerinden query’e imkan vermesi, crossdomain’i kolaylıkla aşması ve HTTP tabanlı olması onu daha uzun süre göz önünde tutacak gibi görünüyor.

Geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere herkese hoşçakalın.

Not:Örnek WebAPI Url(İptal): http://webapiblog.azurewebsites.net/api/products?xml=true

Source Code: http://www.borakasmer.com/projects/WebApiBlog

 

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

7 Cevaplar

  1. Romairo dedi ki:

    Güzel bir makale. Ancak girişteki REST ile ilgili açıklama biraz kafa karıştırıcı. Önce restful Javascript ile data çekmek meşakatli ve yorucu deniliyor ardından web api bu basitleşmiştir çünkü REST tabanlıdır deniliyor. Bu durumda REST ‘in kendisinden çok REST kullanan Javascript sorunlu olduğu sonucu çıkıyor herhalde.

  2. borsoft dedi ki:

    Wcf ile kullanılan rest servisler’de cross domain sorunu ve configuration çok karmaşık idi.WebAPI ile makalede de belirttiğim gibi basit birkaç adım ile kolaylıkla aşılabilmektedir.Restful demekle WebAPI kendisi altyapıda bu teknolojiyi kullanmaktadır.
    İyi günler.

  3. Yiğit dedi ki:

    Hocam merhaba,

    Elinize saglik,
    Fakat webinar seklinde de bir uygulama gelistirme sansiniz olsa keske :)

    • borsoft dedi ki:

      Selam Yiğit;
      Webinar değil de bir daha ki seminer de zaten webapi’yi de kapsayan bir konu hazırladım.
      Zamanı gelince beklerim.

      Hoşçakal.

  4. Emre dedi ki:

    Güzel makale, elinize sağlık.

  5. Murat dedi ki:

    Hocam elinize sağlık güzel bir paylaşım olmuş. Hocam bir sorum olacaktı, hazırladığımız bu WebApi’yi Azur değilde normal ftp lere nasıl yükleyeceğiz? Bu konuda bilgi verirseniz çok sevinirim.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.