Asp.NET Core 2.1 – HttpClientFactory Sınıfı İle Http Isteği Yapma

Merhaba,

.NET Core geliştiricileri, önceki sürümlerde ileri sürülen HttpClient sınıfının türlü sorunlarına istinaden HttpClientFactory sınıfını geliştirmişlerdir. HttpClientFactory sınıfı arka planda HttpClient sınıfının bir instance’ı üzerinden güçlendirilmiş memory management gerçekleştirerek çalışmakta ve olası hataları minimize etmektedir. Bizler bu içeriğimizde güçlendirilmiş HttpClientFactory sınıfının nasıl kullanıldığına dair konuşacağız.

Peki HttpClient sınıfının sorunları neydi?
Kompleks işlemlerde birden fazla HttpClient nesnesiyle çalışma ihtiyacı hissettiğimiz zaman bu işlem eski sürümlerdeki ilgili sınıf ile gerçekleştirmek oldukça maliyetli bir hal alıyordu. Her bir instance remote server için yeni bir connection olacağından dolayı birden fazla instance’ın söz konusu olduğu durumlarda uygulama için kullanılabilecek soketlerin tüketilmesi söz konusu olmaktaydı.

İşte HttpClientFactory sınıfı ile birden fazla HttpClient nesnesinin doğru yönetimi gerçekleştirilmekte ve dolayısıyla bahsedilen durumlardan dolayı süreçteki olası hatalar ortadan kaldırılmaktadır.

HttpClientFactory sınıfını kullanabilmek için üç farklı yaklaşım benimseyebiliriz; Bunlar

  • Doğrudan Kullanma
  • Named Client Oluşturma
  • Typed Client Oluşturma

Şimdi gelin sırasıyla yukarıdaki yaklaşımları ele alalım;

HttpClientFactory Sınıfının Doğrudan Kullanımı

Controller contructer’ı üzerinden inject edilerek direkt kullanabiliriz.

    public class HomeController : Controller
    {
        private readonly IHttpClientFactory _httpClientFactory;
        public HomeController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        public async Task<ContentResult> GetHTML()
        {
            HttpClient _httpClient = _httpClientFactory.CreateClient();
            _httpClient.BaseAddress = new Uri("https://www.gencayyildiz.com/blog");
            string result = await _httpClient.GetStringAsync("/");
            string title = result.Substring(result.IndexOf("<title>") + 7, result.IndexOf("</title>") - result.IndexOf("<title>") - 7);

            return Content(title);
        }
    }

Named Client Oluşturarak Kullanımı

Bir diğer kullanım ise ilgili domaine özel named client oluşturmaktır.

Aşağıdaki gibi belli bir adrese birden fazla istek yapıldığı durumlarda HttpClient nesnesinin handikabını ortadan kaldırmakta ve daha performanslı bir çalışma icra etmektedir.
Olmaması gereken çalışma;

    public class HomeController : Controller
    {
        private readonly IHttpClientFactory _httpClientFactory;
        public HomeController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        public async Task<ContentResult> GetHTML()
        {
            HttpClient _httpClient = _httpClientFactory.CreateClient();
            _httpClient.BaseAddress = new Uri("https://www.gencayyildiz.com/blog");
            string result = await _httpClient.GetStringAsync("/");
            string title = result.Substring(result.IndexOf("<title>") + 7, result.IndexOf("</title>") - result.IndexOf("<title>") - 7);


            string result2 = await _httpClient.GetStringAsync("/blog");
            string description = result2.Substring(result2.IndexOf("<p class=\"site-description\">") + 28, result2.IndexOf("Gençay Yıldız...") - result2.IndexOf("<p class=\"site-description\">") - 28);

            return Content((title, description).ToString());
        }
    }

Yukarıdaki gibi “https://www.gencayyildiz.com/blog” adresine özel birden fazla isteği organize edebilmek için aşağıdaki gibi custom client oluşturarak yönetebilir ve hızımıza hız katabiliriz.

    public class Startup
    {

        .
        .
        .
        public void ConfigureServices(IServiceCollection services)
        {
            .
            .
            .
            services.AddHttpClient("gencayyildiz", c =>
            {
                c.BaseAddress = new Uri("https://www.gencayyildiz.com/blog");
                c.DefaultRequestHeaders.Add("OzelKey", "Ozel-Key");
            });
            .
            .
            .
        }
        .
        .
        .
    }

Olması gereken çalışma;

    public class HomeController : Controller
    {
        private readonly IHttpClientFactory _httpClientFactory;
        public HomeController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        public async Task<ContentResult> GetHTML()
        {
            HttpClient _httpClient = _httpClientFactory.CreateClient("gencayyildiz");
            string result = await _httpClient.GetStringAsync("/");
            string title = result.Substring(result.IndexOf("<title>") + 7, result.IndexOf("</title>") - result.IndexOf("<title>") - 7);

            string result2 = await _httpClient.GetStringAsync("/blog");
            string description = result2.Substring(result2.IndexOf("<p class=\"site-description\">") + 28, result2.IndexOf("Gençay Yıldız...") - result2.IndexOf("<p class=\"site-description\">") - 28);

            return Content((title, description).ToString());
        }
    }

Typed Client Oluşturarak Kullanımı

Son kullanım tarzı ise ilgili domaine özel custom typed client sınıfı oluşturmaktır.

    public class CustomHttpClient
    {
        public HttpClient Client { get; private set; }

        public CustomHttpClient(HttpClient httpClient)
        {
            httpClient.BaseAddress = new Uri("https://www.gencayyildiz.com/blog");
            httpClient.DefaultRequestHeaders.Add("OzelKey", "Ozel-Key");
            Client = httpClient;
        }
    }

Sınıfı tasarladıktan sonra uygulamaya dahil edilen HttpClient servisinin ilgili sınıf tipinde olmasını belirtelim.

    public class Startup
    {

        .
        .
        .
        public void ConfigureServices(IServiceCollection services)
        {
            .
            .
            .
            services.AddHttpClient<CustomHttpClient>();
            .
            .
            .
        }
        .
        .
        .
    }

Haliyle bu düzenlemeden sonra ilgili adrese istek gönderebilmek için Controller’da HttpClientFactory’i değil oluşturduğumuz custom typed class’ı inject etmemiz yeterlidir.

    public class HomeController : Controller
    {
        private readonly CustomHttpClient _customHttpClient;
        public HomeController(CustomHttpClient customHttpClient)
        {
            _customHttpClient = customHttpClient;
        }

        public async Task<ContentResult> GetHTML()
        {
            string result = await _customHttpClient.Client.GetStringAsync("/");
            string title = result.Substring(result.IndexOf("<title>") + 7, result.IndexOf("</title>") - result.IndexOf("<title>") - 7);

            return Content(title);
        }
    }

Typed Client, Named Client yaklaşımına nazaran aynı işi daha mimarisel bazda ve nesnel olarak ele almaktır. Lakin her ikiside aynı adrese birden fazla istek yapılacağı durumda yersiz maliyetlerden arındırılmıştır ve oldukça performanslıdır.

İlgilenenlerin faydalanması dileğiyle…

Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

2 Cevaplar

  1. hakan dedi ki:

    Çok faydalı bir yazı olmuş teşekkürler. Sormak istediğim bir şey var, elimde iki adet url var ilk url ile istek yaptıktan sonra dönen sonuç ile ikinci urlye bir istek göndermem gerekiyor ancak httpclient instance oluşturulduktan sonra base address değiştirmeye izin vermiyor. Başka bir typed client daha oluşturmadan yapmanın bir yolu var mıdır?

    • Gençay dedi ki:

      Merhaba,
      BaseAdress; HttpClient nesnesi singleton olarak inşa edildiğinden dolayı url’i bir kereye mahsus tanımlatmaktadır ve değiştirmeye müsaade etmemektedir. Eğer süreci sağlıklı geçirmek istiyorsanız herbir talebe özel typed client oluşturmanızda fayda var.

      Tabi burada isteğiniz doğrultusunda Named Client’ta kullanabilirsiniz.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*

Copy Protected by Chetan's WP-Copyprotect.