C# İle Httpclient Kullanarak Dış Kaynaklı Veri Çekme Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu eğitimdeki kod örneklerini çalıştırabilmek için bilgisayarınızda .NET SDK (yazılım geliştirme kiti) yüklü olmalıdır. Güncel projelerde performans ve bellek yönetimi açısından .NET 8 veya 9 sürümlerini kullanmanız önerilir.

  • IDE: Visual Studio 2022 veya JetBrains Rider.
  • SDK: .NET 9 SDK.
  • Bilgi Seviyesi: Temel C# sözdizimi ve asenkron (async/await) programlama mantığı.

Projelerinize başlamadan önce, NuGet paket yöneticisi üzerinden System.Net.Http kütüphanesinin projenize dahil olduğundan emin olun. Modern .NET projelerinde bu kütüphane varsayılan olarak yüklü gelmektedir.

HttpClient Kullanımında Temel Prensipler

HttpClient, HTTP isteklerini göndermek ve almak için kullanılan temel sınıftır. Ancak, HttpClient'ı her istekte using bloğu ile oluşturup yok etmek, "socket exhaustion" (soket tükenmesi) problemine yol açar. Bu nedenle, HttpClient'ın singleton (tekil) veya IHttpClientFactory aracılığıyla yönetilmesi kritik öneme sahiptir.

Aşağıdaki örnekte, basit bir GET isteğinin nasıl yapıldığını görebilirsiniz:


using System.Net.Http;

public class VeriServisi
{
    private static readonly HttpClient _httpClient = new HttpClient();

    public async Task VeriGetirAsync(string url)
    {
        HttpResponseMessage cevap = await _httpClient.GetAsync(url);
        cevap.EnsureSuccessStatusCode(); // Hata durumunda exception fırlatır
        string icerik = await cevap.Content.ReadAsStringAsync();
        Console.WriteLine(icerik);
    }
}

Bu kodda static bir HttpClient örneği kullanarak kaynakların verimli kullanılmasını sağlıyoruz. EnsureSuccessStatusCode metodu, dönen HTTP durum kodunun 200-299 aralığında olmasını garanti eder.

IHttpClientFactory ile Güvenli İstek Yönetimi

Üretim ortamındaki uygulamalar için IHttpClientFactory kullanmak, DNS değişikliklerine uyum sağlamak ve bağlantı havuzunu yönetmek için en iyi pratiktir. Bu yöntem, HttpClient örneklerinin ömrünü otomatik olarak yönetir.


// Program.cs içerisine eklenmesi gereken servis kaydı
builder.Services.AddHttpClient("DışServis", client =>
{
    client.BaseAddress = new Uri("https://api.ornekveri.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/json");
});

Servis kaydı yapıldıktan sonra, bağımlılık enjeksiyonu (Dependency Injection) ile bu istemciyi sınıfınıza dahil edebilirsiniz.


public class VeriCekici
{
    private readonly IHttpClientFactory _httpClientFactory;

    public VeriCekici(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public async Task VeriAl()
    {
        var client = _httpClientFactory.CreateClient("DışServis");
        var sonuc = await client.GetStringAsync("veriler");
        Console.WriteLine(sonuc);
    }
}

Bu yaklaşım, uygulamanızın ölçeklenebilirliğini artırır ve bağlantı yönetimi hatalarını minimize eder.

JSON Verilerini Deserialize Etme

Dış kaynaktan gelen veriler genellikle JSON formatındadır. Bu verileri C# nesnelerine dönüştürmek için System.Text.Json kütüphanesini kullanırız.


using System.Text.Json;

public class Kullanici
{
    public int Id { get; set; }
    public string Ad { get; set; }
}

// İstek sonrası dönüştürme işlemi
var jsonCevap = await client.GetStreamAsync("kullanicilar/1");
var kullanici = await JsonSerializer.DeserializeAsync(jsonCevap);
Console.WriteLine($"Kullanıcı Adı: {kullanici.Ad}");

GetStreamAsync kullanımı, veriyi doğrudan bellek üzerinde işleyerek büyük dosyalarda performans avantajı sağlar.

Kritik Güvenlik Uyarısı: Dış kaynaktan gelen verileri asla doğrudan veritabanı sorgularınızda kullanmayın. Her zaman gelen veriyi doğrulayın (validation) ve gerekirse temizleyin. SQL Injection riskine karşı parametreli sorgular veya ORM araçları (Entity Framework Core) kullanın.

Hata Yönetimi ve Dayanıklılık (Resilience)

Ağ hataları, zaman aşımları veya sunucu tarafındaki geçici kesintiler kaçınılmazdır. Bu durumları yönetmek için Polly kütüphanesi ile "Retry" (tekrar deneme) stratejileri uygulayabilirsiniz.


// Polly ile basit bir tekrar deneme stratejisi
var policy = HttpPolicyExtensions
    .HandleTransientHttpError()
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

// Bu policy'yi HttpClientFactory ile entegre edebilirsiniz.

Bu yapı, bağlantı başarısız olduğunda işlemin otomatik olarak üstel bir artışla tekrar denenmesini sağlar.

Yöntem Karşılaştırma Tablosu

Yöntem Avantaj Dezavantaj
Static HttpClient Basit, hızlı kurulum DNS güncellemelerini algılamaz
IHttpClientFactory Bağlantı havuzu yönetimi, güvenli Konfigürasyon gerektirir
Using Blokları Kolay kullanım Soket tükenmesine yol açar

Sıkça Sorulan Sorular

HttpClient ile POST isteği nasıl atılır?

PostAsJsonAsync metodunu kullanarak bir nesneyi doğrudan JSON olarak gönderebilirsiniz. Bu yöntem, serileştirme işlemini otomatikleştirir.

Zaman aşımı (Timeout) nasıl ayarlanır?

HttpClient örneğinin Timeout özelliğini TimeSpan kullanarak belirleyebilirsiniz. Örneğin: client.Timeout = TimeSpan.FromSeconds(30);.

HTTPS sertifika hatalarını nasıl aşarım?

Geliştirme ortamında geçici olarak sertifika doğrulamasını devre dışı bırakabilirsiniz ancak bunu asla üretim ortamında yapmayın. Üretim ortamında geçerli SSL sertifikaları kullanın.

Dış kaynaktan gelen veriyi nasıl önbelleğe alırım?

IMemoryCache kullanarak sık değişmeyen verileri bellekte tutabilir, böylece her istekte ağ trafiği oluşturmaktan kaçınabilirsiniz.

HttpClient'ta özel başlık (Header) nasıl eklenir?

client.DefaultRequestHeaders.Add("Authorization", "Bearer token_degeri"); satırı ile her isteğe özel başlıklar ekleyebilirsiniz.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanacağınız API anahtarlarını, şifreleri veya hassas bilgileri kod içerisinde hard-coded (sabit) olarak saklamayın; bunları Environment Variables veya Azure Key Vault gibi güvenli yönetim araçlarında tutun.

HttpClient ile Performans Optimizasyonu ve Bağlantı Havuzu Yönetimi

HttpClient nesnesinin yanlış kullanımı, özellikle yüksek trafikli uygulamalarda "Socket Exhaustion" (Soket Tükenmesi) sorununa yol açabilir. .NET ortamında performanslı bir veri çekme süreci için bağlantı havuzunun (connection pooling) nasıl yönetildiğini anlamak kritiktir.

Varsayılan olarak HttpClient, bağlantıları açık tutar ancak DNS değişikliklerini algılamakta zorlanabilir. Bu durumu yönetmek ve performansı artırmak için PooledConnectionLifetime özelliğini yapılandırmanız önerilir.


// Program.cs veya Startup.cs içerisinde yapılandırma
builder.Services.AddHttpClient("MyApiClient", client =>
{
    client.BaseAddress = new Uri("https://api.ornek.com/");
})
.ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
    // Bağlantının havuzda kalma süresini kısıtlayarak DNS güncellemelerini yakalar
    PooledConnectionLifetime = TimeSpan.FromMinutes(2) 
});

Bu yapılandırma, bağlantıların belirli bir süre sonra yenilenmesini sağlayarak hem bellek kullanımını optimize eder hem de dış servisteki altyapı değişikliklerine karşı uygulamanızın duyarlı kalmasını sağlar.

HttpClient İsteklerini Birim Testleri ile Doğrulama

Dış kaynaklı verilerle çalışan servislerinizi test ederken gerçek API'lara istek atmak, hem maliyetli hem de kararsız test sonuçlarına (flaky tests) neden olabilir. Bunun yerine HttpMessageHandler sınıfını taklit ederek (mocking) testlerinizi izole edebilirsiniz.

Aşağıdaki örnekte, Moq kütüphanesi kullanarak bir HttpClient isteğinin nasıl simüle edileceğini görebilirsiniz:


public async Task GetData_ReturnsExpectedResult()
{
    // Arrange
    var handlerMock = new Mock();
    handlerMock
       .Protected()
       .Setup(
          "SendAsync",
          ItExpr.IsAny(),
          ItExpr.IsAny()
       )
       .ReturnsAsync(new HttpResponseMessage
       {
          StatusCode = HttpStatusCode.OK,
          Content = new StringContent("{ 'id': 1, 'name': 'Test Verisi' }")
       });

    var httpClient = new HttpClient(handlerMock.Object);
    var service = new MyDataService(httpClient);

    // Act
    var result = await service.FetchDataAsync();

    // Assert
    Assert.Equal("Test Verisi", result.Name);
}

Bu yöntem, ağ bağımlılığı olmadan kodunuzun mantığını doğrulamanıza olanak tanır. Özellikle CI/CD süreçlerinde, dış API'ların kapalı olduğu durumlarda bile testlerinizin başarılı bir şekilde çalışmasını sağlar.

İleri Düzey İpucu: İstekleri Sıkıştırma (GZip/Brotli)

Büyük veri setleri ile çalışırken bant genişliğini korumak ve yanıt sürelerini düşürmek için HTTP sıkıştırmasını aktif etmek oldukça etkilidir. HttpClient, varsayılan olarak Accept-Encoding başlığı ile sunucudan sıkıştırılmış veri talep edebilir.

Eğer sunucu destekliyorsa, AutomaticDecompression özelliğini kullanarak gelen verinin otomatik olarak açılmasını sağlayabilirsiniz:


var handler = new SocketsHttpHandler
{
    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Brotli
};

var client = new HttpClient(handler);
// Artık gelen yanıtlar otomatik olarak dekomprese edilecektir.

Bu küçük dokunuş, özellikle mobil cihazlar veya düşük hızlı ağlarda çalışan uygulamalarınızın kullanıcı deneyimini önemli ölçüde iyileştirecektir.

Sonuç

C# ile HttpClient kullanarak dış kaynaklı veri çekme süreci, doğru mimariyi kurduğunuzda oldukça güvenli ve performanslıdır. IHttpClientFactory kullanımı, JSON serileştirme teknikleri ve hata yönetimi stratejileri, profesyonel bir yazılımın temel yapı taşlarıdır. Bir sonraki adım olarak, GraphQL API'ları ile veri çekme yöntemlerini inceleyebilir veya projenize bir "Circuit Breaker" mekanizması ekleyerek sisteminizi daha dayanıklı hale getirebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Emre Cansever

Teknik rehberler ve kendin yap (DIY) projeleri üzerine yoğunlaşıyorum. Detaylı ve güvenilir içerikler hazırlayarak okuyucuların teknik sorunlarını çözmelerine yardımcı oluyorum.

Yorumlar (0)

Yorum Yaz