Content Negotiation: JSON, XML ve Diğer Medya Türleri
Aynı API, farklı istemciler tarafından farklı formatlarda tüketilmek istenebilir: web uygulamaları JSON, eski kurumsal sistemler XML, yüksek performanslı mikroservisler Protobuf tercih edebilir. Content Negotiation (İçerik Pazarlığı), HTTP'nin bu ihtiyacı karşılayan mekanizmasıdır. İstemci ve sunucu, istek/yanıt formatı üzerinde standart başlıklar aracılığıyla anlaşır.
1. Temel Mekanizma: Accept ve Content-Type
Content Negotiation iki HTTP başlığı üzerinden yürür:
Accept (İstemci → Sunucu): İstemci, hangi medya tiplerini kabul ettiğini ve tercih sırasını (q değeri ile) belirtir.
http
Accept: application/json, application/xml;q=0.9, text/plain;q=0.8
Bu örnekte istemci öncelikle JSON, ikinci olarak XML, üçüncü olarak düz metin istemektedir.
Content-Type (Sunucu → İstemci): Sunucu, yanıtın hangi formatta olduğunu bildirir.
http
Content-Type: application/json; charset=utf-8
Ek Başlıklar:
-
Accept-Charset: Karakter kodlaması tercihi (ör. UTF-8). -
Accept-Encoding: Sıkıştırma tercihi (gzip, br). -
Accept-Language: Dil tercihi (tr, en).
2. Yaygın Medya Tipleri
| Medya Tipi | Kullanım Alanı |
|---|---|
application/json |
Modern REST API'ler, web/mobil uygulamalar (varsayılan) |
application/xml |
Kurumsal entegrasyon, eski sistemler, SOAP |
application/x-protobuf |
Yüksek performanslı mikroservis iletişimi |
application/x-msgpack |
JSON'a alternatif, daha küçük binary format |
text/csv |
Veri dışa aktarma, raporlama |
application/problem+json |
RFC 9457 hata yanıtları |
application/octet-stream |
Ham binary veri (dosya indirme) |
3. ASP.NET Core'da Content Negotiation
ASP.NET Core, ObjectResult ve [ApiController] ile Content Negotiation'ı otomatik destekler. Varsayılan olarak JSON döner; XML ve özel formatlar için formatter eklenmesi gerekir.
A. XML Desteği Ekleme
csharp
// Program.cs
builder.Services.AddControllers()
.AddXmlSerializerFormatters(); // veya AddXmlDataContractSerializerFormatters()
Bu eklendikten sonra, Accept: application/xml gönderen istemciye otomatik olarak XML döner.
B. Özel Formatter: CSV Örneği
csharp
public class CsvOutputFormatter : TextOutputFormatter
{
public CsvOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/csv"));
SupportedEncodings.Add(Encoding.UTF8);
}
protected override bool CanWriteType(Type type)
=> typeof(IEnumerable<>).IsAssignableFrom(type) || type.IsArray;
public override async Task WriteResponseBodyAsync(
OutputFormatterWriteContext context, Encoding selectedEncoding)
{
var response = context.HttpContext.Response;
var items = (IEnumerable<object>)context.Object;
await response.WriteAsync("Id,Name,Price\n");
foreach (var item in items)
{
var props = item.GetType().GetProperties();
var values = props.Select(p => p.GetValue(item)?.ToString() ?? "");
await response.WriteAsync(string.Join(",", values) + "\n");
}
}
}
// Kayıt
builder.Services.AddControllers(options =>
{
options.OutputFormatters.Add(new CsvOutputFormatter());
});
Artık Accept: text/csv gönderen istemci, veriyi CSV formatında alır.
4. Format Zorlama: Accept vs. Query Parametresi
Bazen istemcinin formatı URL üzerinden belirtmesi istenir. İki yaklaşım vardır:
| Yaklaşım | Örnek | Avantaj | Dezavantaj |
|---|---|---|---|
Accept başlığı |
Accept: application/xml |
HTTP standardı | Tarayıcıda test zor |
| Query parametresi | ?format=xml |
Kolay test, görünür | Önbellek karmaşası, REST dışı |
ASP.NET Core'da [FormatFilter] attribute'ü ile query parametresinden format okunabilir:
csharp
[HttpGet("{id}")]
[FormatFilter]
public IActionResult GetProduct(int id, [FromQuery] string format)
{
var product = _service.Get(id);
return Ok(product); // ?format=xml → XML formatter
}
Öneri: Üretim API'lerinde Accept başlığını tercih edin; query parametresini yalnızca test/debug için kullanın.
5. Ne Zaman Hangi Format?
| Senaryo | Öneri |
|---|---|
| Web/mobil uygulamalar | application/json (varsayılan) |
| Kurumsal SOAP/XML entegrasyonu | application/xml |
| Yüksek performanslı iç mikroservisler | application/x-protobuf veya gRPC |
| Veri dışa aktarma (Excel, muhasebe) | text/csv |
| Hata yanıtları | application/problem+json |
Not: Çoğu API için JSON yeterlidir. XML ve diğer formatları yalnızca gerçek bir ihtiyaç varsa ekleyin; her ek format, test ve bakım yükünü artırır.
6. En İyi Pratikler
| Pratik | Açıklama |
|---|---|
| JSON'u varsayılan yapın | İstemci Accept göndermezse JSON dönün. |
Vary: Accept başlığını ekleyin |
CDN ve proxy'lerin farklı formatları ayrı önbelleklemesini sağlar. |
| Desteklenen formatları dokümante edin | OpenAPI dokümanında her endpoint için desteklenen medya tiplerini belirtin. |
| Bilinmeyen formatları reddedin | 406 Not Acceptable ile geçersiz Accept başlığını yanıtlayın. |
| Charset'i belirtin | Content-Type: application/json; charset=utf-8 |
Sonuç
Content Negotiation, bir API'nin farklı istemci ihtiyaçlarına tek bir arayüz üzerinden cevap vermesini sağlayan esnek ve standart bir mekanizmadır. JSON, modern API'lerin varsayılan formatıdır; XML ve özel formatlar yalnızca gerçek bir ihtiyaç olduğunda eklenmelidir. ASP.NET Core, Accept başlığı ve ObjectResult ile bu süreci otomatik yönetir; özel formatter'lar ile CSV, Protobuf gibi formatlar da desteklenebilir. Doğru yapılandırıldığında, API'niz hem esnek hem de performanslı olur. Unutmayın: Her ek format, bir esneklik kadar da bakım yüküdür; ihtiyaç kadarını desteklemek, en sağlıklı yaklaşımdır.