Content Negotiation: Medya Türleri

Content Negotiation (İçerik Pazarlığı), istemci ve sunucu arasında en uygun veri formatını (medya tipini) seçme sürecidir. Bu yazıda, HTTP Accept/Content-Type başlıkları, JSON, XML, Protobuf, MessagePack gibi formatlar, ASP.NET Core'da içerik pazarlığı yapılandırması, özel formatter'lar, format seçim stratejileri ve en iyi pratikler ele alınır.

Content Negotiation: Medya Türleri

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:

  1. ObjectResult Seçimi (Varsayılan): Accept başlığına göre ilgili formatter seçilir.

  2. Özel Format Seçimi: [FormatFilter] attribute'ü ile URL'den format okunur.

  3. İstemci Zorlaması: İstemci, Accept başlığı veya query parametresi ile formatı belirtir.


6. En İyi Pratikler

  1. JSON Varsayılan Yapın: application/json, web API'leri için standart formattır. Varsayılan olarak JSON döndürmeyi tercih edin.

  2. Desteklenen Formatları Belgelendirin: API dokümantasyonunuzda hangi formatların desteklendiğini açıkça belirtin.

  3. Accept Başlığını Doğru Kullanın: İstemci, tercih ettiği formatı Accept başlığı ile net bir şekilde belirtmeli ve q değerlerini doğru ayarlamalıdır.

  4. Güvenlik: Bilinmeyen formatlar için güvenlik açıklarına karşı dikkatli olun. Sadece güvendiğiniz formatları destekleyin.

  5. Cache ve Vary: Vary: Accept başlığını yanıta ekleyerek, farklı formatlar için ayrı cache'ler oluşturulmasını sağlayın.

  6. 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.

Tüm yazılar