Content Negotiation: JSON, XML ve Diğer Medya Türleri
Content Negotiation (İçerik Pazarlığı), HTTP protokolünün temel özelliklerinden biridir. İstemci ve sunucu arasında, bir kaynağın (resource) hangi formatda (medya tipi) teslim edileceğine karar verme sürecidir. İstemci, Accept başlığı ile hangi formatları tercih ettiğini belirtirken; sunucu, Content-Type başlığı ile hangi formatı döndüğünü bildirir. Bu mekanizma, API'lerin farklı istemci ihtiyaçlarına (JSON, XML, Protobuf, vb.) cevap vermesini sağlar. Bu yazıda, Content Negotiation'ın temel prensiplerini, HTTP başlıklarının rolünü, .NET/ASP.NET Core'da nasıl yapılandırılacağını ve en iyi pratikleri ele alacağız.
1. HTTP Başlıkları ve Çalışma Prensibi
Content Negotiation, ağırlıklı olarak iki HTTP başlığı üzerinden gerçekleşir:
A. Accept (İstemci → Sunucu)
İstemci, bu başlık ile hangi medya tiplerini (MIME types) kabul ettiğini ve tercih sırasını (quality value - q) belirtir.
text
Accept: application/json, application/xml;q=0.9, text/plain;q=0.8
Bu örnekte istemci öncelikle JSON istediğini, XML'i ikinci, düz metni ise üçüncü sırada tercih ettiğini belirtmektedir.
B. Content-Type (Sunucu → İstemci)
Sunucu, yanıtın hangi formatta olduğunu bu başlık ile bildirir.
text
Content-Type: application/json
C. Accept-Charset, Accept-Encoding, Accept-Language
-
Accept-Charset: Karakter kodlaması (örn. UTF-8). -
Accept-Encoding: Sıkıştırma algoritması (örn. gzip, br). -
Accept-Language: Dil tercihi (örn. tr, en).
Sunucu, bu başlıkları değerlendirerek en uygun formatı, sıkıştırmayı ve dili seçer.
2. Yaygın Medya Tipleri ve Kullanım Alanları
| Medya Tipi (MIME Type) | Açıklama | Kullanım Alanı |
|---|---|---|
application/json |
JavaScript Object Notation | Modern REST API'ler, web/mobil uygulamalar |
application/xml |
Extensible Markup Language | Eski sistemler, SOAP, kurumsal entegrasyon |
application/octet-stream |
Ham ikili veri (binary) | Dosya indirme, yükleme |
text/plain |
Düz metin | Loglar, basit mesajlar |
text/html |
HTML | Web sayfaları (tarayıcı) |
application/x-protobuf |
Protocol Buffers | Yüksek performanslı microservis iletişimi |
application/x-msgpack |
MessagePack | JSON'a alternatif, daha küçük boyutlu binary format |
application/yaml |
YAML | Konfigürasyon dosyaları, OpenAPI |
image/png, image/jpeg |
Görüntü formatları | Resim dosyaları |
3. ASP.NET Core'da Content Negotiation
ASP.NET Core, Content Negotiation'ı ObjectResult ve ApiController ile otomatik olarak destekler. Varsayılan formatter'lar application/json, text/json ve text/plain desteği sunar.
A. Varsayılan Davranış
csharp
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
var product = new { Id = id, Name = "Laptop" };
return Ok(product); // ObjectResult döner
}
}
Bu durumda, ASP.NET Core Accept başlığını kontrol eder. Eğer Accept: application/xml gelirse, XML formatter devreye girer (eğer yapılandırıldıysa).
B. XML Desteği Ekleme
csharp
// Program.cs
builder.Services.AddControllers()
.AddXmlSerializerFormatters(); // veya AddXmlDataContractSerializerFormatters()
C. Özel Formatter (Örnek: CSV)
csharp
// 1. CSV formatter sınıfı
public class CsvOutputFormatter : TextOutputFormatter
{
public CsvOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/csv"));
SupportedEncodings.Add(Encoding.UTF8);
}
protected override bool CanWriteType(Type type)
=> typeof(IEnumerable<object>).IsAssignableFrom(type);
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
var response = context.HttpContext.Response;
var items = context.Object as IEnumerable<object>;
// CSV'ye dönüştür ve yaz
await response.WriteAsync("Id,Name,Price\n");
foreach (var item in items)
{
// ... CSV satırlarını yaz
}
}
}
// 2. Formatter'ı ekle
builder.Services.AddControllers(options =>
{
options.OutputFormatters.Add(new CsvOutputFormatter());
});
D. Format Zorlama (URL veya Query Parametresi ile)
Bazen istemcinin formatı URL'de veya query parametresinde belirtmesi istenir.
csharp
[HttpGet("{id}")]
public IActionResult GetProduct(int id, [FromQuery] string? format)
{
// format parametresi ile zorla (örn. ?format=json)
if (format == "xml")
{
return Ok(product); // XML formatter seçilir
}
return Ok(product); // Accept başlığına göre normal negotiation
}
4. Accept vs. Format Parameter: Hangisi Ne Zaman?
| Özellik | Accept Başlığı | Format Parametresi (URL/Query) |
|---|---|---|
| HTTP Standardı | ✅ Evet | ❌ Hayır (Özel) |
| Kullanım Kolaylığı | 🟡 Orta (header ayarlamak gerekir) | 🟢 Kolay (URL'de görünür) |
| Cache Desteği | ✅ Evet | ⚠️ Dikkat (farklı URL = farklı cache) |
| Tarayıcı Testi | 🔴 Zor | 🟢 Kolay |
| Önerilen Kullanım | API'ler (mobil/web) | Geliştirme, test, dokümantasyon |
Öneri: Üretim API'lerinde Accept başlığını, geliştirme/test sırasında ise query parametresini (?format=json) kullanmayı tercih edin.
5. Content Negotiation Stratejileri
ASP.NET Core, ObjectResult içinde format seçimi için üç strateji sunar:
-
ObjectResult Seçimi (Varsayılan):
Acceptbaşlığına göre ilgili formatter seçilir. -
Özel Format Seçimi:
[FormatFilter]attribute'ü ile URL'den format okunur. -
İstemci Zorlaması: İstemci,
Acceptbaşlığı veya query parametresi ile formatı belirtir.
6. En İyi Pratikler
-
JSON Varsayılan Yapın:
application/json, web API'leri için standart formattır. Varsayılan olarak JSON döndürmeyi tercih edin. -
Desteklenen Formatları Belgelendirin: API dokümantasyonunuzda hangi formatların desteklendiğini açıkça belirtin.
-
AcceptBaşlığını Doğru Kullanın: İstemci, tercih ettiği formatıAcceptbaşlığı ile net bir şekilde belirtmeli veqdeğerlerini doğru ayarlamalıdır. -
Güvenlik: Bilinmeyen formatlar için güvenlik açıklarına karşı dikkatli olun. Sadece güvendiğiniz formatları destekleyin.
-
Cache ve Vary:
Vary: Acceptbaşlığını yanıta ekleyerek, farklı formatlar için ayrı cache'ler oluşturulmasını sağlayın. -
Performans: Binary formatlar (Protobuf, MessagePack), JSON ve XML'e göre daha hızlıdır ve daha az bant genişliği kullanır. Yüksek performans gerekiyorsa, bu formatları düşünün.
Sonuç
Content Negotiation, API'lerin farklı istemci ihtiyaçlarına (JSON, XML, Protobuf, vb.) cevap vermesini sağlayan esnek ve standart bir mekanizmadır. ASP.NET Core, Accept başlığı ve ObjectResult ile bu süreci otomatik olarak yönetir. JSON varsayılan formattır; XML, CSV, Protobuf gibi özel formatlar ise formatter eklenerek desteklenebilir. Doğru yapılandırıldığında, API'niz hem esnek hem de performanslı olacaktır.