Sayfalar

15 Eylül 2019 Pazar

Wep Api




ASP.net ve Web API

Bu makalede Web API ve SQL Server kullanarak örnek veritabanı Northwind üzerinden bir uygulama yapacağız. Bir Model ve Controller kısmımız olacak. View’i ise client olarak düşünebiliriz. Amacımız bir kategoriler controller’ı ile kategorileri görüntülemek olacak.

Web API nedir?

Web API bir web servisi teknolojisi, RESTFull bir servisdir.
ASP.net ise Microsoft’un ürettiği bir web geliştirme platformudur.
İçerisinde bir MVC yapısı barındırmaktadır.
Web API teknolojisini kullanarak kullanıcıyla anında iletişime geçebilen Real-Time applicationlar yapabilabilir.

SOA, SOAP ve RESTFull

SOA benzetecek olursak Object Oriented gibi bir yazılım geliştirme yaklaşımıdır.
Service Oriented Architecture olarak kısalttığımız bu yapı bildiğimiz web servisleri içeriyor.
Bu yapının altında SOAP ve Restfull dediğimiz yapılar var.
Gerekli yapıların birbiriyle entegrasyonunu sağlamak için kullanılıyor.
Basit bir şekilde şöyle düşünebiliriz: Projelerde kullandığımız çok katmanlı mimaride business logic katmanı ile data layer’ı ayrı bir proje yaparak bunu web ortamında sunuyoruz.
Client tarafı ise bunlardan bağımsız oluyor. Sonuç olarak client ve web servis tarafını birbirinden ayırıyoruz.
SOAP – Simple Access Object Protocol – Bu yapının belli başlı standartları var.
Güvenlik, performans. WCF .net tarafında kullanılıyor. Tamamen bir XML çıktısı üretiyor.
Bu XML ise aslında envelop tagleri arasında bir header ve body nin bulunduğu bir yapı.
Bununla belli başlı uygulamaları haberleştirebiliyoruz.
Restfull ise daha sonra ortaya çıkan bir teknoloji. Temsili durum transferi (representational state transfer) anlamına geliyor. Çok esnek ve rahat tamamen HTTP protokolüne odaklı. SOAP’da TCP HTTP tercihi yapabilirken burada tamamen HTTP üzerindeyim bunun artısı da web üzerinde çok rahat bir şekilde Web API tarafında kullanabileceğim bir yapı olması oluyor.
Restfull servislerin döndürdüğü veri tipi konusunda katı kuralları yok. İstenilen formatta geri dönüş sağlayabiliyor. Güvenlik anlamında ise birez zayıf o yüzden kendi güvenlik yapılarımızı inşa etmemiz gerekebiliyor. Günümüz teknolojilerinde bunun da daha rahat yolları var.
Servis mimarilerinde kritik nokta platform bağımsız biçimde çalışabilmek. Dönen json data Java’da,PHP’de, .Net de okunabiliyor. JSON web ortamında hızlı javascript’e entegre. Performans açısından boyut çok önemli.
XML:
JSON:
  • Burada name etiketi XML’de iki defa kullanılırken JSON gösteriminde bir defa kullanılıyor dikkat ederseniz.
  • Mobil burada bir diğer kritik noktayı oluşturuyor. Çoğu mobil uygulama servisle haberleşmek durumunda. Servis kullanıldığında Android, iOS olması fark etmiyor.
    Her işimizi JSON objeleriyle görebiliyoruz.
  • Web API performans olarak avantajları arasında caching ve asenkron yapılar yine söz konusu.
  • JSON kullanımına şöyle bir örnek verilebilir: ASP.net 4’de config yapısı XML formatındadır. Artık ASP.net 5’de bu bile JSON’a döndü.
  • Biz de projemiz içerisinde veritabanından çektiğimiz verileri JSON formatında dışarıya servisle açıp yine dışarıdan gelen JSON objelerini database’imize kaydedeceğiz.
  • Proje içerisinde NORTHWND veritabanını kullanacağız. SQL Server ve Northwindveritabanının hazır olması gerekiyor.
  • Management Studio ile veritabanımızı bir kontrol edelim. Daha sonra bu kısımda sıkıntı yaşamak istemiyoruz çünkü.
    • Örneğin servisin aşağıdaki gibi açık olması gerekiyor.

Projenin Oluşturulması

  • File > New > Project diyerek projemizi oluşturmaya başlayalım. Web altında ASP.NET Web Application seçip isim veriyorum.
  • Empty Template altından Web API‘ı açıyorum. Özellikle öğrenirken boş template üzerinden gitmek daha faydalıdır.
  • Bir MVC projesi açıldığında bunun bir tarafında da bir web servisi de host edilebilir. Ama bu çok ihtiyacımız olan bir yapı olmuyor. Ama böyle bir imkan var ihtiyaç olursa.
  • Solution Explorer‘da gördüğünüz gibi MVC’den alışkın olduğumuz Model‘lar Controller‘lar var ama gördüğünüz gibi bir View yok. View kısmı client olarak düşünülebiliriz.
  • Models içerisine Orm ve Dto klasörleri oluşturalım. Entity Framework yapısını Orm klasörünün içerisinde, Data Transfer Objelerimiz olacak Dto’ları da Dto klasörü içerisinde saklayacağız.

Database ve ORM

  • Orm içerisine Add>New Item diyerek Data sekmesi altında ADO.net Data Entity Model ekleyelim. Northwind örnek database’i ile çalışacağız.
  • Gelen pencerede EF Designer from database seçili direk Next diyoruz. New Connection dedik.
  • Server Name kısmına . yazıp Windows Authentication‘u seçelim. Database olarak NORTHWND‘ı seçip onaylayalım.
  • Entity Framework 6.x versiyonunu kullanıyoruz. Yalnızca Tables diyerek tabloları ekleyelim.
  • İşlem tamamlandığında database bağlantısı gerçekleştirilip gerekli ORM yapısı kurulmuş oldu. Artık kodumuzu yazmaya başlayabiliriz.

Controllers Sınıfı

  • Controllers klasörü içerisine yine Add>New Item diyerek bir Web API 2 Controller - Empty controller oluşturalım.
  • Bu controller kategorileri döndürecek. İsim olarak CategoryController verelim. Namespace tanımlamaları altında karşımıza gelen böyle bir yapı oldu:
  • Bunun bir Web Api olmasını sağlayan ApiController class’ının içerisindeki yapılar.
  • Entity’den instance alalım öncelikle. Web.config içerisinde <connectionstrings> altında <add name="NORTHWNDEntities"... ile NORTHWNDEntities olarak gözüküyor. Namespace’imizi ekliyoruz.
1
2
3
4
5
6
7
8
9
10
11
12
using _1110_WebApi.Models.Orm;
 
// ...
 
namespace _1110_WebApi.Controllers
{
    public class CategoryController : ApiController
    {
        NORTHWNDEntities db = new NORTHWNDEntities();
 
    }
}
 
 
 
Bu controller’a kategoriler için gerekli işlemleri yapacak metodları yazacağız. Kategorileri getirmek ile başlayalım. Fakat kategorileri getirecek metodu tanımlamadan önce yapmamız gereken bir şey var.

DTO – Data Transfer Objesi

  • Bir servis kullanıyorsak gerek güvenlik gerekse performans anlamında bir data transfer objesi kullanmalıyız. Örneğin Product class’ına baktığımız zaman çok sayıda property’si olduğunu görüyoruz. Şimdi bu noktada bir servisi dışarıya açarken ben hepsini birden dışarıya açmak istemeyebiliriz. Bu güvenlik açısından işimize gelmeyebilir. Karşı tarafın buna ihtiyacı olmayabilir. Sunucumuzun performansını buna harcamak istemeyebiliriz. Bu noktada da ben bu değerleri bir transfer objesi üzerinden bunları dışarıya açacağız.
  • Bunun için Dto klasörünün içerisine CategoryModel isimli bir class oluşturalım. İçerisine aşağıdaki gibi gerekli propertyleri giriyorum.
  • prop yazıp iki kere tab tuşuna basarsanız daha hızlı eklemeniz mümkündür. Visual Studio içerisinde bunlara snippet denir. ctrl+k ctrl+x yaparak diğer snippetleri görebilirsiniz.
  • Ne yaptık? CategoryModel adında bir Dto ve iki adet property’sini oluşturduk. Şimdi artık dışarıya açacağımız Model’in tipini CategoryModel olarak seçeceğiz.
  • ORM’nin içerisindeki Category class’ı üzerinden değil de CategoryModel class’ı üzerinden veri çıkışını gerçekleştireceğiz.
  • Artık Controller içerisine geri dönebiliriz. CategoryModel’leri barındıran bir list döndürecek aşağıdaki fonksiyonu oluşturalım.
  • Yukarıdaki tanımlanan GetAllCategories bütün kategorileri döndüren bir metod.
  • Bu metod içerisine List<CategoryModel> catlist = db.Categories.ToList(); dersek db.Categories.ToList() ile bütün kategorileri döndürmüş oluyoruz.
  • Bunun yerine ToList() demeden önce buna bir select yaparak CategoryModel tipinde bu listeyi çekeceğiz.
  • İçerisinde DTO’nun KategoriAdi ve Aciklamasi propertylerini databaseden gelen CategoryName ve Description kategorilerine eşleyeceğiz.
  • Bu liste artık bana KategoriAdi ve Aciklamasi databaseden gelen değerlerle dolu bir liste halinde sunulacak.
  • Bu listeyi de return edeceğiz.

XML Yerine JSON ve Route Ayarları

  • Bu aşamada projeyi Build edip çalıştırdığımızda karşımıza çıkan sayfada HTTP Error 403.14 - Forbidden hatası alıyoruz.
  • Fakat /api/category dediğimiz takdirde xml formatında database’imdeki bütün kategorileri dışarıya açmış oldum.

  • Peki burada iki action olsa ne olacaktı? Category altında birden fazla fonksiyon da olabilir.
  • Bu noktada da App_Start altında WebApiConfig.cs içerisinden yapacağımız rootconfig yapılandırması ile beraber action adını da istiyoruz.
  • WebApiConfig.cs içerisinde routeTemplate: "api/{controller}/{id}", satırını routeTemplate: "api/{controller}/{action}/{id}", ile değiştirelim.
  • Artık action adı olan GetAllCategories‘i de URL’e eklememiz gerekecek.
  • /api/category/GetAllCategories dediğimizde yine önceki değerleri görüntülebiliyoruz.
  • Bu noktada az önceki gibi bütün kategorilere rahatlıkla erişebiliyorum ve daha sonra yazacağım ikinci bir metoda da rahatlıkla erişebileceğim.
  • XML yerine JSON döndürmek için yine aynı dosyada // Web API configuration and services diye belirtilmiş kısmın altında,
Yukarıdaki satırı ekleyerek default olarak belirtilen XML yapısını temizlediğim takdirde bu sefer bana JSON döndürecektir.

  • Eğer id’sine göre tek bir kategori döndürmek istiyorsak GetAllCategories dışında yeni bir metod tanımlamamız gerekiyor.
  • Bunun için CategoryController.cs dosyamızı açalım. GetAllCategoriesden sonrasına GetCategoryByID fonksiyonu tanımlayalım.
  • Yeni fonksiyonumuz tek bir kategori döndüreceğinden bildirilmesi public CategoryModel GetCategoryByID(int id) şeklinde olacak.
  • Dışarıdan da parametre olarak id alıyor.
  • Dışarıdan aldığımız bu idye göre de database’den de o id’li kategoriyi yakalayacağız.
Peki bu id nasıl gelecek? Hatırlarsanız WebApiConfig içerisindeki default yapılandırmada bir id vardı:
Buradaki id sayesinde bu id atanacak.
  • Artık /api/category/getCategoryByID/2 diyerek id’si 2 olan kategoriyi döndürebilirim.
  • Burada önemli bir nokta metodun adının başındaki Get‘in request’in tipini belirten bir anahtar kelime olmasıdır.
  • O Geti sileresek metodun get requesti olduğu anlaşılmaz. Örneğin metodu CategoryByID olarak değiştirirsek çalışmayacaktır:
  • Bundan kaçınmanın bir diğer yolu ise metodun başında tipini belirtmektir:
  • Bu şekilde yazdığımızda metodun isminin başında Get yazmasa da çalışacaktır.
  • Özel bir neden yoksa ilk seferdeki gibi metodun isminde belirtmek daha doğru olacaktır.
  • Fiddler, Postman gibi toollarla GET requesti gönderip sonucu inceleyebiliriz.

  • 200 status kodu isteğin (request) başarılı olduğu anlamına gelir.

  • Yukarıda response’u yani sunucunun verdiği cevabı ham haliyle görebiliyoruz. İlk satır status code bilgisi, altındakilerin ise HTTP headerları olduğunu görüyoruz.
    Bu bilgiler gelen verinin künyesi gibi düşünülebilir.

POST Metodu ile Database Insert İşlemi

  • Bu noktaya kadar yalnızca GET metodlarıyla çalıştık. Ama HTTP yalnızca GET metodlarıyla sınırlı değil.
  • POST metodu ile gönderdiğimiz veriyi database’imize kaydetmeyi deneyelim.
  • Northwind içerisinde categories tablosuna bakacak olursak:

  • Bu tablo içerisine kategori ekleyeceğiz. Öncelikle CategoryController.cs dosyamıza bir POST metodu yazalım.
  • Metodun dönüş tipi IHttpActionResult olacak. Bu tamamen arkada asenkron çalışan bir yapıya sahip bir action result tipi.
  • Metodun ismini AddCategory yapalım. Adında bir POST anahtar kelimesi kullanmadığım için attribute olarak üstünde bunun bir POST metodu olduğunu belirtmeliyiz.
İçerisine yazacağımız return statement’da ise return Json(""); gibi bir dönüş yapabiliriz.
Ama bundan ziyade return Ok(); diyebiliriz. Burada ok dediğimiz 200 status kodlu herşey yolunda cevabı oluyor.
Buradan benzer şekilde birçok HTTP word’ünü –NotFound() veya BadRequest() gibi- döndürmek mümkündür.
Fonksiyonumuza parametre olarak ise Dto’da belirttiğimiz CategoryModel tipinde bir nesne veriyoruz.
İçerisinde database ile bağlantı kurulacak bölümü yazmadan önce nesnenin dolu geldiğini görüyor olmam gerekiyor.
Debug modunda fonksiyona breakpoint koyup çalıştırdıktan sonra. Fiddler veya Postman’den aşağıdaki adrese altındaki içeriği gönderelim.
Request’i gerçekleştirirken Content-Type:application/json header’ını da belirtmemiz gerekiyor.
İlgili url’e bir request gerçekleştiğinde uygulamamız bunu yakalayacak.

  • Yukarıda request ile gönderilen verinin başarıyla obje içerisine geçmiş olduğunu görüyoruz.
  • Şimdi gönül rahatlığıyla database’e kaydetme işlemini gerçekleştirebiliriz.
  • Tekrar aynı request’i gönderirek bu sefer veritabanına kaydedildiğini görüyoruz.
  • Böylece temel veritabanı işlemimizi gerçekleştirdik.

Cross Origin (CORS) – Başka Domainden Erişme

  • Geliştirdiğimiz API’ye client tarafından erişmek istediğimizde şöyle bir hata ile karşılaşmamız olasıdır:

  • Bu bir güvenlik mekanizması aslında. API’mize yabancı bir adresten erişilmesi durumunda browser http header’ında bunun için bir izin arıyor. Bu noktada servisten tüm client’ların veri okumasına izin verebiliriz. Böylece yalnız kendi domaininden değil internetteki başka biri de bu bilgiye erişilebilir.
  • Bunu da Web.config dosyası içerisinden <system.webServer> altına şu satırları ekleyerek yapacağız:
  • Artık servisten herhangi bir data get etmek isteyen herkese erişim izni veriyoruz.
  • Buradaki * isteyen herkesin bu dataya erişebilmesi anlamına geliyor.
  • Bu noktada server tarafında gereken işlemleri tamamladık. Artık geriye aşağıdaki gibi bir client aracılığıyla veriyi düzenlemek kalıyor.

  • Client için bir MVC projesi oluşturabilir veya basit bir web sayfası kullanarak ajax ile erişim sağlayabiliriz.
  • Client tarafı bir Android uygulaması da olabilir. Burada önemli olan web api ile bir API oluşturup araya bir katman sokarak bir soyutlama sağlamış olmaktır. Ardından ise bu katmanın güvenliğini sağlamak gerekir.
  • Client kısmını ise bir sonraki yazıda ele alacağız.
  • ASP.net’in sitesine girdiğimizde gerek Web API gerekse MVC konusunda gerekli dökümanlara ulaşabiliriz.
 

MVC LOADING TOO SLOW ISSUE