Erhan Ballıeker

Asp.Net Core API Backend ve Xamarin.Forms İle Kelime Oyunu Bölüm 2 (Asp.Net Core SignalR ve Azure SignalR Service)

Selamlar,

Xamarin Forms Mobile App ve Asp.Net Core backend tabanlı kelime oyunumuzdan bir önceki yazımda bahsetmiştim. Bu 1 aylık macerada yaşadıklarımızı ve kullandıklarımızı örneklerle anlatmaya devam ediyorum

Bu yazımda kullanıcıları aynı üzerinde oynatmak ve online olarak göstermek için faydalandığımız teknolojiden – ki herhangi bir .net projenizde bir şekilde bir realtime ihtiyacınız varsa kullanmanızı önereceğim teknoloji olan –  SignalR dan bahsedeceğim.

Aslında daha da doğrusu Asp.Net Signalr Core dan bahsedeceğim. SignalR ve SignalR Core farklı iki API. Asp.Net Core ile beraber yeniden geliştirilmeye başlandı.

Biliyorsunuz ki bir uygulama da realtime ihtiyacımız olduğunda kullanabileceğimiz birçok yöntem var, bunlar;

  • Web Socket
  • Server Sent Events (SSE)
  • Long Polling
  • Short Polling

vs gibi birden çok seçeneğimiz var. En tavsiye edilen en yeni yöntem tabii ki websocket kullanmak. Ama yazdığınız uygulama her ne ise (web-mobil-desktop vs) kullanacak olan clientları ve kullanacakları donanım ve yazılımları bilemeyeceğiniz için sadece kalkıpta tüm iletişimi WebSocket ile kurmak çok doğru olmayacaktır, size kullanıcılar kaybettirecektir.

Peki SignalR ne yapıyor?

SignalR önce gerçek zamanlı haberleşme isteyen client ın kontrolünü yapıyor. İlk denediği seçenek WebSocket kullanarak haberleşmek eğer client bu teknolojiyi desteklemiyorsa sırası ile SSE, LongPolling vs deneyerek en sonunda doğru yöntemi bulup iletişimi sağlıyor.

Bir asp.net core projemizde signalr kullanmakta çok basit artık. Biliyorsunuz ki Asp.Net core da artık koca MVC akışı bi pipeline olarak proje ekleniyor. SignalR da bu şekilde projeye ekleniyor ve kullanmaya başlıyorsunuz.

Öncelikle biz Asp.Ne Core API projemizde bunun için neler yaptık buna bakalım.

Microsoft.AspNetCore.SignalR paketini kullandık. Bu paketi eğer projenizde Microsoft.AspNetCore.App paketi varsa indirmenize gerek yok zaten bu paket mevcut halde gelmiş oluyor.

Bundan sonra yapmanız gereken Signalr ın projenizle ilişki kurduğu Hub sınıfını oluşturmak.

Bizim projemiz içerisinde GameHub adında bir hub ımız mevcut.Aşağıdaki gibi bir kısmını inceleyelim.

public class GameHub : Hub
    {
        public IServiceProvider Services { get; }
        public GameHub(IServiceProvider services)
        {
            Services = services;
        }

        public async void ConnectToHub(string username)
        {
            await Clients.Caller.SendAsync("ConnectedToHub", username, Context.ConnectionId);
            await Clients.AllExcept(Context.ConnectionId).SendAsync("NewUserConnectedToHub");
        }

        ...

Burada constructor tarafında kullandığımız ServiceProvider a çok takılmayın şimdilik. Bu aşağıda başka metodlar da application service ler tarafında yazdığımız ve container a register ettiğimiz serviceleri almak için kullandığımız yöntem. constructor injection yapamazdık çünkü Hub sınıfı parametresiz Constructor ı bulup çağıracaktır.

ConnectToHub metodunda iki şey yaptık.

  • Bu metodu çağıran Client ın kendisin deki –Clients.Caller diyerek-  Client tarafta ki ConnectedToHub metodunu çalıştırmasını söyledik. Parametre olarak ta signalr ın kendi oluşturmuş olduğu Context.ConnectionId yi geçtik, çünkü kullanıcıyı kendi db mizde online olarak update etmek ve bu kullanıcıyla doğrudan haberleşmelerde bu ContextId yi kullanmamız gerekeceği için o bağlantı boyunca saklamak istedik.
  • Kullanıcı bir şekilde disconnected olduğunda signalr client tarafta zaten böyle bir event i tetikleyecek bizde kullanıcıyı offline olarak işaretleyip sakladığımı ConnectionId sini sileceğiz, taa ki yeniden bağlanıp yeni connectionId sini öğrenene kadar.
  • İkinci satırda ise, uygulamada zaten mevcut oturum açmış insanların telefonunda online user sayını arttırabilmek yani yeni birinin geldğini söyleyebilmek adına, Clients.AllExcept(Context.ConnectionId) diyerek yani bu metodu çağıran kişi dışında herkese bir sinyal göndererek client tarafta NewUserConnectedToHub metodunu çalıştırmak istediğimizi söyledik.

Hub tarafında bu ve benzeri başka metodların tanımı dışında birşey yok.

Gelelim bu signalr ı Asp.net core un request pipeline ına nasıl eklediğimize.

public void ConfigureServices(IServiceCollection services)
        {
            // CORS
            services.AddCors();

            // MVC
            var mvc = services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            //SignalR 
            services.AddSignalR()
                    .AddAzureSignalR("Endpoint=...;AccessKey=...;Version=...;");

              ........

Startup tarafındaki ConfigureServices metoduna yukarıda gördüğünüz gibi AddSignalR diyerek SignalR service lerini kullanacağımızı söyledik. Biz bu projede signalr ın backend tarafı scale edilme yönetmi olarak Azure SignalR Service i kullandığımız için AddAzureSignalR diyerek içerisine azure tarafında oluşturmuş olduğumuz service url i ve accesskey i verdik. Azure SignalService tarafına daha sonra gelicem. Şimdilik SignalR ile devam edelim.

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...
            app.UseMvc();
            app.UseAzureSignalR(routes =>
            {
                routes.MapHub("/game");
            });
            ...
        }

Configure metodunda ise UseAzureSignalR diyerek AzureSignalService kullanacağımızı ve hub ımızı register etmiş olduk. Eğer AzureSignalService kullanmadan sadece SignalR ı eklemek isteseydik kod aşağıdaki gibi olacaktı.

app.UseSignalR(builder => builder.MapHub("/game"));

SignalR Client (Xamarin Forms)

Api tarafında Signalr ı ne şekilde kurup kullandığımızdan bahsettim. Xamarin Forms projemizde de signalr kullanmak için yaptığımız ilk şey aşağıdaki paketi tüm forms projelerine indirmekti

Microsoft.AspNetCore.SignalR.Client (1.1.0)

Bundan sonra uygulamanın App.cs tarafında aşağıdaki gibi HubConnectionBuilder  ı kullanarak kullanıcıyı hub a bağladık.

 public App()
        {
            InitializeComponent();

            Connection = new HubConnectionBuilder()
               .WithUrl("http://appserversitename.net/game")
               .Build();

            Connection.Closed += async (error) =>
            {
                IsConnectedToHub = false;
                await Task.Delay(new Random().Next(0, 15) * 1000);
                MessagingCenter.Instance.Send(this, "Disconnected");

                var disconnectResult = await ApiClient.UserApi.DisconnectUser(new Models.Models.Dto.Request.User.DisconnectUserRequestModel { Username = InMemorySettings.GetCurrentUser().Username });

                await Connection.StartAsync();
            };

            RegisterSignalrEvents();

            ....

Connection ın kapanması durumunda signalr bizim için bir event tetikliyor burada da istediğimiz diğer işlemleri yazdık.

RegisterSignalREvents metodumuz da ise, API tarafında kullanıcı tarafında şu metodları tetikle dediğimiz metodları oluşturduk. örnek olarak API tarafı client tarafında ConnectedToHub metodu tetiklediğinde ne olacağını, Connection.On metodu ile parametreleri de vererek, içeriye yazdık.

private void RegisterSignalrEvents()
        {
            Connection.On<string, string>("ConnectedToHub", (user, connectionId) =>
             {
                 Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
                 {
                     try
                     {
                         await ApiClient.UserApi.ConnectUser(new Models.Models.Dto.Request.User.ConnectUserReqModel { ConnectionId = connectionId, Username = user });

                         var onlineUserCount = await ApiClient.UserApi.GetOnlineUsers();

                         Device.BeginInvokeOnMainThread(() =>
                         {
                             MessagingCenter.Instance.Send(this, "OnlineUserCountReceived", onlineUserCount);
                         });

                         InMemorySettings.GetCurrentUser().ConnectionId = connectionId;
                         MessagingCenter.Instance.Send(this, "Connected");

                         IsConnectedToHub = true;
                     }
                     catch (Exception ex)
                     {
                           ...
                     }
                 });
             });

Burada basitçe kullanıcıyı db de online olarak set edip, signalrdan gelen connection id sini saklayıp, uygulama tarafında başka yerleri xamarin.forms un messaging center ını kullanarak tetikliyoruz. Aşağıdaki gibi o an kaş kişi oynuyor bunu görmemiz için kullandığımız yöntem bu idi.

WhatsApp Image 2019-05-31 at 22.10.45 (1)

ApiClient.. şeklindeki haberleşme yapısına benzer yapıyı nasıl kurduğumuza bakmak için aşağıdaki yazılarımı okuyabilirsiniz.

Client tarafında bundan fazla bir numara yok.

Gelelim Azure SignalR Service i neden kullandığımıza. Daha önceleri SignalR kullandıysanız bir gerçek hayat senaryosunda ve büyük bir projede signalr ı ya azure service bus ile ya redis ile yada mssqlserver ile desteklemişsinizdir. Bunun temel sebepleri hem signalrı scalable kılmak hemde daha persistant bir yapı oluşturmak diyebiliriz. İşte artık Azure Signalr Service ile bunları düşünmekten kurtuluyorsunuz. Bu şöyle oluyor. Artık kullanıcılar eskiden olduğu gibi doğrudan sizin appserver ına bağlanmıyorlar, sizin appserver ınızdan bir url alıp (negotiation url) Signalr Service e bağlanıyorlar, sizin app server ınızda buraya bağlanıyor ve nihayetinde client ile appserver ınız arasında realtime persistant bir connection kurulmuş oluyor.

Aşağıdaki görsel bunu anlatıyor.

Capture.PNG

Asp.net Core SignalR için, Signalr Service, hub başına 5 adet websocket açıyor. Bu service i ücretsiz olarak maximum 20 concurrent user için deneyebilirsiniz. Bu da zaten test etmeniz için yeterli bir sayı. Daha sonra concurrent kullanıcınız arttıkça paralı tarifeye geçip binlerce kullanıcıyı concurrent birşekilde yönetme ve realtime birbirini bağlama işini Azure a bırakabilirsiniz.

Azure portal e girdiğiniz de All Services den Web sekmesini tıklayarak ücretsiz bir SignalR Service oluşturun ve en kısa sürede denemeye çalışın derim.

Capture.PNG

Bu yazımda da yazmış olduğumuz kelime oyunu için realtime kısmını hem server hem de client tarafta nasıl çözdük ve azure signal service i neden nasıl kullandığımızı anlattım.

Bir sonraki yazımda görüşmek üzere.

Asp.Net Core API Backend ve Xamarin.Forms İle Kelime Oyunu Bölüm 1 (Proje Yapısı, Teknolojiler ve Lottie)

Selamlar,

Eğlenceli bir seri ile karşınızdayım. Xamarin’i 2012 den beri aktif olarak takip eden ve gönülden destekleyen biri olarak her fırsatta gücünü göstermek için elimden geleni yapıyorum. Muhtemelen bir xamarin ekibini bir de DreamTheater ı bu kadar yürekten savunup reklamını yapmışımdır.  =)

Haziran ayının ilk haftası içerisinde store a atmaya hazırlandığımız ve 1 ay gibi kısa bir sürede (Normal mesai dışında) geliştirdiğimiz xamarin.forms ile yazılmış ve backend tarafında Asp.Net Core kullandığımız uygulamamızın arayüzlerinin bir kısmını, bu uygulamayı yaparken kullandığımız teknolojileri sizlerle örnekler yaparak paylaşmak istedim.

Uygulamanın ara yüz örnekleri aşağıdaki gibi.

Evet store da onlarcası olan bir kelime oyununu yaptık =) Maksat ya bu da tutarsa dan fazlası. İnsanlara xamarin ile kısa sürede yapılabilecekleri göstermek de sebepleri arasında. Tabi ekstra özellikler de koyacağız zamanla ama şuanki haliyle hem kendi kendinize hem de online kişilerle aynı anda oynayabilme seçenekleri ile storeda kilerden fonksiyonalite olarak pek bir fazlası yok, ama ui konusunda daha gösterişli olduğumuzu düşünüyoruz:)

Gelelim 1 ay gibi kısa bir sürede bu oyunu neler kullanarak tamamladık.

Solution tarafında temel projelerimiz şu şekilde idi.

  • 1 Asp.net core api projesi.
  • 1 Xamarin.Forms projesi. (Standard lib, ios ve android)
  • Geçen yazılarımda göstermiş olduğum gibi bir API client projesi
  • Boggle algoritmasını kullanarak oyunları oluşturup sakladığımız bir Console App
  • Gerisi de yardımcı Utils tadında class libraryler diyebilirim.

Daha detaylı olarak kullandığımız teknolojiler ise aşağıdak gibi;

  • Asp.Net Core SignalR
  • Azure SignalR Service
  • Azure MSSQL Database
  • EF Core
  • Asp.Net Core
  • Xamarin.Forms
  • Lottie

Evet temel seviyede bunlardan daha farklı kullandığımız birşey yoktu aslında. Klasik bir katmanlı yapı içerisinde data önden arkaya gidip geliyor 🙂

Uygulamadan bahsedecek olursak, projenin tamamlanması için önemli iki konu vardı

Birincisi parmağınızla harflerin üzerinde gezerek kelime oluşturucağınız komponent in yapımı

İkincisi de bu komponent te kelimelerin doğru şekilde yerleştirilemsi tabii ki 🙂

İkinci konuyu Boggle algoritması ile çözebiliyorsunuz. Detaylarına girmiyeceğim tabii ki ama araştırmak isteyen olursa şuradan başlayabilir.

İkinci sorunumuzun çözümü iOS tarafında basit idi, ama android tarafında 0 dan GridView oluşturup ekrana basmak durumunda kaldık. Detayına sonradan gireceğim ama şunu söylemeden edemeyeceğim CustomRenderer yazarken iOS tarafındaki şu sihirli metodu android tarafında çok arayacaksınız.

Xamarin.Forms.Platform.iOS dll i altındaki ;

protected internal virtual UIView GetControl();

Xamarin forms projelerinizde CustomRenderer yazarken artık Native taraftasınız bildiğiniz gibi. Bu GetControl, Xamarin Forms tarafındaki oluşturmuş olduğunuz componenti size ios tarafında komple UIView olarak veriyor. zaten herşey orada UIView olduğu için herşey çok güzel. Android tarafta ise 128198321 tane Widget ve Layout olduğu için(bu kadar olmasa da fazlaca)  işler daha da karışabiliyor.

Peki bazı sayfaların detaylarına girip nerede neyi nasıl kullandık kısmına gelmeden önce, yukarıda ayrıca yazmış olduğum Lottie kütüphanesinden bahsetmek istedim.

Bu o kadar başarılı bir kütüphane ki ister native ister crossplatform bir uygulamay yazıyor olun, herhangi bir yerde herhangi bir animasyon oynatmak en basit işleriniz arasına giriyor bunun sayesinde.

Bu projede bizde bolca kullandık. Bu yüzden bu yazıyı Lottie ye örneklendirme yaparak bitirmek istiyorum.

Xamarin.Forms projelerinizin tümüne yani hem kod paylaşımı yaptığınız .NetStandard hem de platform spesifik projelere projelere aşağıdaki kütüphaneyi nugetten indiriyorsunuz.

Com.Airbnb.Xamarin.Forms.Lottie

İster kendi tasarımcılarınızın çizdiği animasyonlar olsun, isterseniz hazır animasyon olsunlar Lottie ile bu animasyonu oynatmak için onun istediği formatta bir json dosyası olarak vermeniz yeterli. Bu formatı tasarımcılarınız nasıl çıkartacaklarını bilirler yada hazır bulduğunuz animasyonlar için zaten download ederken bu şekilde gelecektir.

Hazır animasyonlar için de bir ton güzel animasyonun olduğu aşağıdaki linki incelemenizi öneririm

https://lottiefiles.com/

Burada illa ki ihtiyacınız olana benzer bir animasyon bulup projenize ekleyebilirsiniz diye düşünüyorum

Peki devam edelim Lottie yi xamarin forms tarafında kullanmamıza. Nuget paketini indirdikten sonra yapacağımız şey şu;

Her iki platform spesifik projeye gidip yani iOS ta AppDelegate e, Android de ise MainActivity ye gidip normal bir plugin kullanımında yaptığımız gibi aşağıdaki kodu yazıyoruz.

AnimationViewRenderer.Init();

LoadApplication(new App()) den önce bu kodu da yerleştirdikten sonra artık kullanmaya hazırız.

Projenizde bir Xaml sayfasına açın. Namespace lerin olduğu kısma aşağıdaki namespace i ekleyin.

xmlns:forms=”clr-namespace:Lottie.Forms;assembly=Lottie.Forms”

Artık projede Lottie animasyonu kullanmaya hazırız. lottifiles sitesine gidip istediğiniz bir animasyonu indirin. Aşağıdaki gibi istediğiniz animasyonun detayına gittiğinizde bazı görsel ve hız özelliklerini de değiştirerek bilgisayarınıza download edin.

Capture

json formatında pc nize indirdiğiniz bu dosyayı iOS projenizde direk Root a (AppDelegate ile aynı yere), Android projenizde ise Assets Folder(yok ise kendiniz oluşturabilirsiniz) ı içerisine ekleyin.

Daha sonra namespaci eklediğiniz xaml sayfasına dönün ve animasyonun ekran içerisinde oynamasını istediğiniz yere aşağıdaki kodu yazın

  <forms:AnimationView WidthRequest="50" 
                       HeightRequest="20"
                       HorizontalOptions="Center" 
                       Scale="4"
                       x:Name="loadingAnimationView"
                       Animation="wave_loading.json" 
                       Loop="true" 
                       AutoPlay="true"/>      

Burada projenize eklediğiniz json dosyasının adını uzantısı ile birlikte Animation propertysine vermeniz yeterli. Burada Loop true diyerek ve AutoPlay true diyerek animasyonun ekran açılınca hemen oynamaya başlamasını ve bittiğinde baştan tekrar başlamasını söylemiş olduk. Bunların tamamını animasyonun oynamasını istediğiniz senaryonuza göre kendiniz customize edebilirsiniz.

OnClick, OnPause, OnPlay vs gibi bir çok yardımcı event ten bir çok propertysine kadar istediğiniz şekilde animasyonu evirip çevirmenize olanak sağlıyor Lottie.

Biz uygulamada ana sayfadan tutunda, günlük ödül verdiğimiz popup a kadar birçok yerde Lottie yi kullandık.

Bu uygulama da kullandıklarımızla ile ilgili şeylerden örnekler le bahsetmeye devam edeceğim.

Bir sonraki örneğimizde görüşmek üzere.

Tüm .Net Client Projelerimizde Ortak Kullanabileceğimiz Bir API Client yazalım Bölüm 2

Selamlar,

Bir önceki yazımda hazırlığını yapmış olduğumuz projemizin asıl kısmına gelelim.

Projemize ApiClient adında bir sınıf ekliyorum ve içeriğini aşağıdaki gibi dolduruyorum. Bir göz gezdirip detaylarına değinelim.


 public class ApiClient
        {
            #region fields

            private static ApiClient shared;
            private static object obj = new object();

            #endregion

            #region properties

            internal static IServiceCollection Services { get; set; }
            internal static IServiceProvider ServiceProvider { get; private set; }
            private static ApiClient Shared
            {
                get
                {
                    if (shared == null)
                    {
                        lock (obj)
                        {
                            if (shared == null)
                            {
                                shared = new ApiClient();
                            }
                        }
                    }

                    return shared;
                }
            }

            #endregion

            #region api spesific properties

            private IRandomUserApi _IRandomUserApi { get => ServiceProvider.GetRequiredService(); }

            //Exposed public static props via ApiClient.Shared 
            public static IRandomUserApi RandomUserApi{ get => Shared._IRandomUserApi; }

            #endregion

            #region ctor

            private ApiClient()
            {
                if (Services == null)
                    Services = new ServiceCollection();

                Init();
            }

            #endregion

            #region internal methods

            private void Init()
            {
                ConfigureServices(Services);
                ServiceProvider = Services.BuildServiceProvider();
            }

            private void ConfigureServices(IServiceCollection services)
            {
                services.AddTransient<ITokenService, TokenService>();

                #region AnonymousApi Configuration

                services.AddRefitClient()
                .ConfigureHttpClient(c =>
                {
                    c.BaseAddress = new Uri("http://wordy.azurewebsites.net/");
                    c.Timeout = TimeSpan.FromSeconds(10);
                })
                .AddTransientHttpErrorPolicy(p => p.RetryAsync())
                .AddHttpMessageHandler(serviceProvider =>
                {
                    var token = serviceProvider.GetRequiredService().GetToken();
                    return new AuthTokenHandler(token);
                });

                #endregion

            }

            #endregion
        }

Yukarıdakilerle alakalı olarak şurayı da okumanızı öneririm.

Burada önceki yazımda projeme eklediğim kütüphaneleri kullanmaya başlıyorum artık.

Yukarıda dönen hikaye şu;

  • Singleton bir ApiClient objem var. Tüm refit interfacelerini birer property üzerinden dışarıya expose ediyorum.
  • ConfigureServices metodunu neredeyse Asp.Net Core daki gibi birebir aynı yapmaya çalıştım. IoC conteiner ı oluşturup, refit interfacelerimi ve polly policy lerimi ilgili enpoint e register ediyor
  • Son olarak aynı şekilde yazmış olduğum DelegatingHandler larıda client ıma ekliyorum ve herşey kullanıma hazır hale geliyor.

Bundan sonra herhangi bir clien projesinde şunu yapabilirim

ApiClient.RandomUserApi.GetUser(“3”);

dediğimde Client projem her ne olursa olsun ister bir core web app ister xamarin ister başka birşey,  httpclient factory üzerinden refit, polly, delegating handler lar da kullanarak güzel yapı kurmuş oluyorum.

Bunları istediğimiz gibi şekillendirip güncelleyip, istediğimiz gibi konfigüre edebiliriz ve hiçbir client projemize dokunmamış oluruz.

Ek olarak burada ITokenService ve TokenService diye bir service yazdım. Bunu da şuna örnek olarak kullanabiliriz. Örneğin kullanıcı mobil uygulama da login olduğunda aldığımız token Xamarin.Essentials s Preference paketi ile saklayarak AuthTokenDelegating handler a parametre olarak verebilmenin örneği olsun diye koydum.

Farkli client projeler de bu ITokenService implemenatasyonlarını ayrı yazarak başka türlü yerlerde saklayıp okuyabiliriz.

Xamarin projesi için bu işimizi görecektir.

   public interface ITokenService
    {
        string GetToken();
    }

Xamarin forms projesi için implementasyon;

    public class TokenService : ITokenService
    {
        public string GetToken()
        {
            if (Preferences.ContainsKey(Constants.AuthToken))
                return Preferences.Get(Constants.AuthToken, string.Empty);
            else
                return string.Empty;
        }
    }

Bunu muhtemelen bu ApiClient projesinde değil de client projelerde register etmek daha doğru olacaktır gerçek hayat senaryolarında.

Bir sonraki yazımda görüşmek üzere.

Tüm .Net Client Projelerimizde Ortak Kullanabileceğimiz Bir API Client yazalım.

Selamlar,

Daha önceden bahsetmiştim böyle bir konuya girmek istediğimi.

Yeni gelen HttpClientFactory ile de beraber daha önceden yazmış olduğum Resilient Network Services serisinin daha kısasını ve güncellenmiş halini kütüphanelerin detayların da çok fazla boğumladan yeniden incelemek istiyorum.

Amacımız şu;

Bir ApiClient Standard kütüphanesi oluşturalım. Solution ne kadar Client projemiz var ise Xamarin, Web, Console, UWP, WPF farketmez hepsi bu kütüphane üzerinden network haberleşmelerini yapsın(Http üzerinden)

Bu işlem sırasında da önceki yazılarımızda kullandığımız refit ve polly hatta akavache yi de kullanalım. ModernHttpClient a artık çok gerek yok, çünkü proje özelliklerinden Default mu yoksa platform spesifik sınıflarımı kullanmak istediğimizi zaten belirtebiliyoruz aşağıdaki gibi.Capture.PNG

Burada HttpClient implementation ın Managed mı Default mu yoksa Android mi olduğunu seçebiliyoruz. iOS tarafında da durum aynı şekilde.

Peki çok uzatmadan bu kütüphanemizi yazmaya başlayalım ve Asp.Net Core Web App ve Xamarin projelerimizde de kullanalım bakalım.

Bir adet boş solution açıp içerisine önce bir adet Asp.Net Core Web App ve bir adet de xamarin.forms projeleri ekleyelim.

Daha sonra Add New Project diyerek Bir adet .netstandard class library ekleyelim.

Capture.PNG

Bu kütüphanenin diğer tüm client projeleri tarafından kullanılabileceğine eminiz çünkü .netstandard kütüphanesi ekledik.

Projede kullanmak istediğimiz ve resilient network services kısmında bize yardımcı olacak 3 temel şey var.

  • Polly
  • Refit
  • HttpClientFactory

Tüm bunların kullanımı için öncelikle aşağıdaki paketleri projeye teker teker ekliyoruz.

  • Microsoft.Extensions.DependencyInjection
  • Microsoft.Extensions.Http.Polly
  • Refit.HttpClientFactory
  • Xamarin.Essentials (xamarin tarafında kullanmak üzere şimdilik çok önemi yok)

Projede kullanmak için bir api yazmaktansa yine open apilardan randomuser  kullanalım.

Bunun için daha önceki yazılarımda çokça detayına girdiğim için burada konuyu uzatmadan hemen refit interface imi oluşturucam. Sonrasında da örnek bir tane delegating Handler oluşturucam

Bunlar aşağıdaki gibi;

Random user api si ile haberleşecek olan Refit Interface i;
Projede Endpoints adında bir klasör açıp içerisine aşağıdaki interface i atıyorum

Burada amaç tüm farklı endpointleri ayrı ayrı interfaceler altında toplayıp hepsini ayrı ayrı konfigüre edebilmek.

 [Headers("Content-Type : application-json")]
    public interface IRandomUserApi
    {
        [Get("/")]
        Task<string> GetUser(string results);
    }

DelegatingHandler ım.

 public class AuthTokenHandler : DelegatingHandler
    {
        private readonly string _token;
        private const string TOKEN = "Authorization";
        public AuthTokenHandler(string token)
        {
            _token = token;
        }

        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (!request.Headers.Contains(TOKEN) && string.IsNullOrEmpty(_token))
            {
                return new HttpResponseMessage(HttpStatusCode.BadRequest)
                {
                    Content = new StringContent("Missing auth token.")
                };
            }
            else if (!request.Headers.Contains(TOKEN) && !string.IsNullOrEmpty(_token))
            {
                request.Headers.Add(TOKEN, $"Bearer {_token}");
            }

            var response = await base.SendAsync(request, cancellationToken);

            return response;
        }
    }

Bu iki kod bloğu ile ilgili daha detaylara girmek isterseniz aşağıdaki yazılarımı okuyabilirsiniz.

Projenin temel kısımları hazır oldu. Bundan sonraki yazımda asıl sınıfımız olan ApiClient sınıfını yazıp client projelerimizde kullanacağız.

Bir sonraki yazımda görüşmek üzere.