httpclientfactory – Erhan Ballıeker
Başlık konusunda biraz kararsız kalmıştım. Değinmek istediğim noktayı şöyle anlatayım. Asp.Net Core projesi dışında bir Client ınız olduğunu düşünelim (Console App, Xamarin Mobile App, WinForms, WPF, UWP vs vs..), bu projeden API call ları HttpClientFactory kullanarak nasıl yapacaksınız buna değinmek istiyorum.
Önceki yazılarımda Networking taraflarındaki konulara çokça değinmişimdir. Günümüzde de bir .net projesinde http üzerinden haberleşmek için artık elimizde en iyi sınıf HttpClientFactory gibi duruyor. Ama danışmanlıklarım sırasında şunu çok gördüm.
Asp.Net Core un genel olarak çalışma yapısı insanlarda oturmamış. Microsoft un tüm paketleri ayrı ayrı yapmasının sebebi çok anlaşılmamış. .NetStandard nedir, Core nedir, kafalarda karışıklıklar var.
Bunlar la ilgili konulara değindiğim yazılarıma bakmanızı tavsiye ederim.
İnernettki örneklerin birçoğu HttpClientFactory kullanımını bir Asp.Net Core projesi üzerinden anlatıyor. Asp.Net Core projesinde ki startup dosyasında IServiceCollection a httpclientfacory yi, named typed vs gibi farklı tiplerde istediğiniz gibi tanıtıp sonra da kullanıyorsunuz.
Ama bir xamarin projesi karşımıza çıktığında ve bu xamarin projesinden dışarıya yapacak olduğumuz requestleri HttpClient ile değilde HttpClientFactory ile olmasını istetdiklerinde, ortalıka ne bir Startup var, ne ServiceCollection vs vs.
Bu durumda yapıpyı kurmakta zorluk çekildiğini gördüm.
Önce şundan bahsedelim.
Asp.Net Core daki IServiceCollection ın Asp.Net Core projesine geldiği dll
Microsoft.Extensions.DependencyInjection paketi. Peki bu paketi ben başka bir .NetStandard kütüphaneme ekleyemez miyim? Evet ekleyebilirim.
.NetStandard ın ne olduğunu hatırlayalım kısaca;
Microsoft un .netframework ünün birden fazla implementasyonu var. Yani bu framework ü bir Interface olarak düşünürseniz farklı implementasyonlardan kastım şunlar olucaktır;
Asp.Net – Asp.Net Core
Tüm bu platformlar arasında kod paylaşımı için .netstandard a kadar iki farklı yönetmimiz var idi. Portable Class Library ler ve Shared Asset Project idi.
Microsoft artık tüm platformlar arasında kod paylaşımını kolaylaştırmak için ortaya bir standard koydu. .NetStandard. Artık her implementasyon bu standard içerisindeki API ları kendine eklemek zorunda idi
İlk başlarda çok fazla API içerisinde barındırmayan .NetStandard artık 2.0 versiyonu ile veraber tüm full .netframework 4.6.1 deki api lara bile sahip hale geldi. İçerisinde artık binlerce API var. Bu da şu demek, eğer nugetten indirdiğiniz bir kütüphane ya da sizin target olarak .NetStandard seçerek oluşturmuş olduğunuz bir kütüphane neredeyse üm .net implementasyonlarında çalışır olucak demek.
Peki bu özet bilgi ile şöyle bir işe kalkışalım. Bir solution ımız olsun. Bu solution içerisinde şunlar olsun.
Bir Asp.Net Core ile yazılmış API
Bir Asp.Net Core Web App (Client)
Bir Xamarin iOS ve Android App (Client)
Bir Console App (Client)
Bir WPF App (Client)
Ve şunu istiyor olalım.
Tüm clienlar çoğunlukla olacağı gibi aynı Apı mız ile haberleşerek istediği işlemleri yapsın. Ve bu Api ile haberleşirken de HttpClient değil HttpClientFactory kullansın.
Hatta Eski yazılarımda olduğu gibi öyle bir Api Haberleşme sınıfı yazalım ki, buraya Refit, Polly gibi kütüphaneleri de kullanıp yine güzel bir Resilient Network Service altyapısı oluşturalım.
Tüm bunlaru yapmadan önce başlıkta dediğim gibi bir xamarin uygulamasında HttpClientFactory yi nasıl kullanırım bunu görelim.
Bunu yapmanın aslında ne kadar basit olduğunu görünce biraz şaşırabilirsiniz özellikle .Netstandard ve .Net Core ile beraber Microsoft un birçok paketi ayrı ayrı sunmasının faydalarını daha önce keşfetmediyseniz…
Bir xamarin uygulamasını neredeyse bir Asp.Net Core uygulaması gibi görünmesini sağlamak için yapmam gereken ilk şey 2 adet paketi .NetStandard kütüphaneme eklemek. Platforms spesifik projelerle şuan için işim yok. Boş bir xamarin.forms projesi açtıktan sonra (Empty template ile) ilk olarak aşağıdaki paketleri yüklüyorum nugetten.
bu iki paket şunlar;
ilk paket ile uygulamama bir DI özelliği katıyorum, bunun içinde autofac, unity, ninject vs gibi bir IoC container kullanmadan Microsft un kendi extension paketi üzerinden yürüyorum. Bu noktada artık bir Asp.Net Core projesinde yaptığımız gibi her istediğimiz api ı bu container a ekleyip bunun üzerinden erişbilir olduk bile.
Diğer pakete de bana Asp.Net Core projesinde DI container a AddHttpClient dememi sağlayan ve HttpClientFactory devreye sokan extension metodun geldiği paket. Bu noktadan itibaren de artık bir core web app e eklediğim gibi ClientFactory yi ekleyebilirim.
Bunun için bir IServiceCollection field ını App.cs tarafında oluşturdum. Eğer null ise Constructor new ServiceCollection diyerek Container ı oluşturuyorum.
Daha sonrada uygulama sayfalarımdan burada register etmiş olduğum service lere ulaşmak için IServiceProvider property mi oluşturuyorum. Bunu ayağa kaldırmak içinde tüm serviceleri register ettikten sonra BuildServiceProvider() diyerek provider objemi oluşturuyorum. App.cs de yapacaklarım bu kadar.
App.cs de gerekli işlemleri bir kaç satır da hallettikten sonra, ki bu birkaç satırda şunları yapmış olduk;
Bir DI mekanizması oluşurup IoC container kurduk
Bu Container a IHttpClientFactory yi register ettik
artık MainPage e geldiğimde, aşağıdaki gibi ServiceProvider üzerinden ilgili service ime ulaşabilirim. Burada ulaşmak istediğimiz service de IHttpClientFactory nin kendisi.
_clientFactory = App.ServiceProvider.GetRequiredService<IHttpClientFactory>();
var result = await _clientFactory.CreateClient().GetStringAsync("http://randomuser.me/api?results=1");
_clientFactory = App.ServiceProvider.GetRequiredService(); dedikten sonra artık bu clienFactory normal bir asp.net core projemdeki gibi elimde. Burada basic usage olarak kullandığımız için hiçbir parametre verdeden CreateClient diyerek HttpClient ımızı oluşturup gerekli işlemlerimizi bunun üzerinden yapabiliriz.
Görmüş olduğunuz gibi Microsoft un Asp.Net Core ile beraber kurmuş olduğu yapı oldukça esnek ve birbiri ile kullanılmaya oldukça müsait. Bir xamarin projemizde HttpClientFactory yi ve hatta Microsoft kendi micro Container ını kullanmış olduk.