Asp.net Web Api ve Content Negotiation Kavramı

20 Mar

Günümüzde artık internet dünyası sadece kişisel bilgisayarlarda internet tarayıcıları tarafından görüntülenebilen web sitelerinden oluşmuyor. Mobil cihazlar, Televizyonlar, Akıllı Evler Aletleri v.b gibi birçok cihaz artık internet aleminde kaynak tüketimine dahil olmuş durumdadır. Şüphesiz bu giderek daha da genişleyecek. Bu çeşitlilik karşısında artık internet dünyasına sunulan bilgilerin nasıl temsil edildiği öne çıkmıştır. Örneğin bir cihaz JSON veri tipiyle işlem yaparken diğeri XML veri tipini tercih ediyor olabilir. HTTP üzerinden kaynak tüketimi göz önüne alındığında verilerin temsili(representation) content negotaition kavramı ile bütünleşiyor.

Bir önceki yazıda HTTP protokolüne özel bir kavram olan Content Negotiation kavramından genel olarak bahsetmiştik. Bu yazıda ise content negotiation konusunu Asp.Net Web api tarafından incelemeye çalışacağız.

Asp.net Web Api teknolojisi Content Negotiation ile uyumlu çalışmaktadır. Ancak bu kavram Web Api teknolojisinin bir parçası gibi anlaşılmamalıdır. Content Negotation kavramı W3C(World Wide Web Consortium) tarafından tanımlanmış bir internet içerik standartıdır. RFC(Request For Comment) döküman numarası 2616‘dır.

Content Negotiation kavramı Asp.net Web Api tarafında, kullanıcıların talebine göre verinin hangi biçimde sunulacağını belirlemek için kullanılan sunucu odaklı bir çözüm yöntemi olarak kullanılmaktadır. Kullanıcılar talep ettikleri ortam döküman türlerini HTTP header bilgisi olarak belirleyebilirler. Talepteki Header bilgisi Web Api tarafından değerlendirilerek uygun şekilde bir cevap oluşturulur ve HTTP protokolü üzerinden kullanıcıya sunulur.

Web Api bir kullanıcının hangi niyetle kaynak talep ettiğini anlamak için talebin(HttpRequest) Header bilgilerini kontrol eder. Header bilgilerinde içerik ile ilgili kısımlar şu şekilde sıralanabilir:

  • Content-Type: API Burada belirtilen formatta veri sunar.
  • Accept: Kullanıcı burada kabul ettiği veri türlerini belirtir. (application/json gibi)
  • Accept-Charset:Kabul edilen karakter kodlaması. (UTF-8 gibi)
  • Accept-Language: Kabul edilen dil seçeneği. (en-us, tr-tr gibi)
  • Accept-Encoding:Kabul edilen içerik kodlaması. (gzip gibi)

Web Api uygulamasına Fiddlr gibi bir araç yardımıyla sorgulamalar yaparak durumu inceleyebiliriz.

Örneğin http://localhost:15063/api/values için bir talep gönderdiğimizde,

fidd1
Header bildirimi yok

Web Api için oluşturulan talepte içerik bilgisine ait bir bildirim yapılmadı. Ancak sonucun JSON formatında geldiğini gözlemliyoruz. Bunun sebebi Web Api uygulamasının varsayılan olarak JSON formatında veri oluşturmasıdır.

Şimdi içerik talebini JSON değilde XML şeklinde istemeyi deneyelim. Bu durumda Content-Type: application/xml şeklinde bir Header bildirimi yapmamız gerekmektedir.

Content-Tyle:application/xml
Content-Tyle:application/xml

Dikat edecek olursak aynı URI üzerinden aynı kaynağa eriştiğimiz halde dönen cevap XML formatı şeklinde oldu. Yani kaynağın temsil ediliş şeklini HTTP Content Negotiation ile değiştirmiş olduk.

Farklı formatlarda veri alma talebini bir MVC uygulaması veya Web Froms ile yapmış olsaydık ya farklı URI üzerinden (sayfa veya action metod) oluşturacaktık, ya da aynı URI adresine parametre olarak kaynak türünü xml şeklinde belirtmiş olmamız gerekebilirdi.

Kullanıcılar Web Api uygulamalarına hangi türde veri kabul ettiklerini Accept header bilgisi ile bildirirler. Örneğin üç farklı formatta veri kabul ettiğimizi bildirecek olursak: Accept: application/xml, application/json, text/javascript

Accept Header
Accept Header

Bu durumda varsayılan değer olan JSON formatı şeklinde veri döner. application/json seçeneğini kaldırırsak bu sefer de XML veri döner.

Web Api tarafında medya tiplerine göre uygun içerik üretmek için Media Type Formatter sınıfları oluşturulur ve akışa dahil edilir. Eğer JSON veya XML gibi türler dışında kendi özel türümüzü oluşturmak istiyorsak System.Net.Http.Formatting.MediaTypeFormatter sınıfından türeteceğimiz sınıflarda istediğimiz veri formatlarını oluşturabiliriz.

 

HTTP Content Negotiation Kavramı

16 Mar

Content Negotiation işleyişi HTTP protokolüne özgü bir kavramdır. Anlam olarak tercüme edecek olursak, client ve server arasında yapılan bir içerik anlaşması veya müzakeresidir diyebiliriz.  Amacı, aynı URI ile farklı döküman türlerinde içerik sunabilmektir. Yani daha genel bir ifadeyle kaynak gösterim şeklinin kullanıcılar tarafından belirlenmesi diyebiliriz. Content Negotiation ile ilgili resmi dökümanlar buradaki w3.org sayfasında bulunmaktadır.

Content Negotaition 1.1
Content Negotaition 1.1

Kullanıcıların sunucu kaynaklarına ulaşmak için kullandıkları internet tarayıcıları kendi yetenek türlerine göre kaynak türünü seçmek için HTTP protokolünde belirlenmiş olan kurallara uygun talepte bulunurlar. Örneğin bir X tarayıcısı JPEG dökümanlarını işleyebilecek yeteneği yoksa fakat PNG dökümanlarını işleyebiliyorsa sorgu sırasında bu isteğini HTTP Accept Header (istek başlığı) bilgisi olarak sunucuya iletir. Örneğin Accept istek başlığı ile sunucuya kullanıcının medya türü tercihini Accept:image/png şeklinde belirtir.

Burada Accept istek başlıkları superset/subset biçiminde temsil edilmektedir. Örneğin Accep:image/png örneğinde “image superset’tir, “png ise subset’tir.

Örnek medya türleri için Accept Header bilgileri:

  • Accept: application/json
  • Accept: image/png
  • Accept: image/*
  • Accept: text/xml

Accept istek başlığında birden fazla tercih de belirtilebilir. Örneğin:

Accept: text/html, text/xml, image/jpeg, */*

Burada talebi gönderen taraf text/html, text/xml, image/jpeg ile açıkça belirtilmiş medya türlerinin tercih ettiğini, bunun yanında */* ile farklı medya türleri varsa onları da kabul edebileceğini  ifade etmektedir. Burada sunulan bir dizi medya türü vardır. Bu medya türlerine üstünlük katsayısı vererek öncelik tercihi yapmak da mümkündür. Örneğin:

Accept: text/html, text/xml, image/jpeg, */* ; q=0.01

Üstünlük katsayısı 1.0 ve 0.0 arasında bir değer alır ve “q” ile gösterilir. Burada text/html gibi üstünlük katsayısı belirtilmemiş türlerin katsayısı otomatik olarak 1.0 atanır. Ancak */* kalıbı 0.01 gibi düşük bir öncelik olarak belirlenmiştir.

İnternet tarayıcıları medya tiplerine göre kendi öncelik katsayılarını belirlerler. İnternet tarayıcıları kullanmadan fiddler gibi bir araç yardımıyla HTTP talepleri oluşturup, Header seçeneklerini kendimiz belirleyebiliriz.

Bir kaynaktan gelen dökümanın medya türü farklı olabileceği gibi dil seçimi de farklı olabilmektedir. Aynı şekilde Accept Header bilgisinde istediğimiz dili belirtebiliriz. Örneğin, Accept-Language: tr şeklinde.

İçerikle ilgili bir diğer Header bilgisi ise Content-Type şeklinde belirtilen ve kaynağa erişmek isteyen kullanıcının hangi medya türünde döküman istediğini bildiren içerik bilgisidir. Örneğin Content-Type:application/json şeklinde belirlenen bir Header bilgisi kullanıcının JSON veri istediğini belirtmektedir.

Günümüzde kaynak kullanımı sadece tarayıcılar tarafından değil, mobil uygulamalar tarafından da ağırlıklı olarak kullanıldığı göz önüne alındığında Content Negotiation kavramı özellikle REST servisler oluşturulurken dikkat edilmesi gereken konulardan bir tanesidir. Çünkü REST servisleri HTTP tabanlı çalıştıkları için servis geliştiriciler olarak HTTP dünyasını ve kurallarını iyi tanımamız gerekmektedir. Bu sayede neyi neden kullandığımızı bilerek ilerleyebiliriz.