{"id":3169,"date":"2020-02-27T17:06:15","date_gmt":"2020-02-27T16:06:15","guid":{"rendered":"https:\/\/gokhan-gokalp.com\/?p=3169"},"modified":"2020-03-02T10:12:21","modified_gmt":"2020-03-02T09:12:21","slug":"asp-net-core-series-05-dont-block-your-code-be-reactive","status":"publish","type":"post","link":"https:\/\/gokhan-gokalp.com\/tr\/asp-net-core-series-05-dont-block-your-code-be-reactive\/","title":{"rendered":"ASP.NET Core Serisi 05: Kod&#8217;unu bloklama, reactive ol"},"content":{"rendered":"<\/p>\n<p>Eskiden sadece belirli bir kesime hitap eden uygulamalar geli\u015ftirirken, g\u00fcn\u00fcm\u00fcz teknoloji \u00e7a\u011f\u0131n\u0131n ilerlemesiyle ve global marketten de bir pay alabilmek i\u00e7in, art\u0131k daha b\u00fcy\u00fck bir kesime hitap eden uygulamalar geli\u015ftirmemiz gerekiyor.<\/p>\n<p>Geli\u015ftirdi\u011fimiz uygulamalar\u0131n <strong>7\/24 kesintisiz hizmet <\/strong>verebiliyor olmas\u0131 ve <strong>response s\u00fcreleri d\u00fc\u015f\u00fck<\/strong> olan, kullan\u0131c\u0131 deneyimi sorunsuz ve y\u00fcksek olan uygulamalar olmas\u0131 da olduk\u00e7a \u00f6nem arz ediyor.<\/p>\n<figure id=\"attachment_3176\" aria-describedby=\"caption-attachment-3176\" style=\"width: 760px\" class=\"wp-caption aligncenter\"><a href=\"\/wp-content\/uploads\/2020\/02\/scalability.jpg\"><img decoding=\"async\" class=\"wp-image-3176 size-full lazyload\" data-src=\"\/wp-content\/uploads\/2020\/02\/scalability.jpg\" alt=\"\" width=\"760\" height=\"400\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/scalability.jpg 760w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/scalability-300x158.jpg 300w\" data-sizes=\"(max-width: 760px) 100vw, 760px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 760px; --smush-placeholder-aspect-ratio: 760\/400;\" \/><\/a><figcaption id=\"caption-attachment-3176\" class=\"wp-caption-text\">https:\/\/coinnewstelegraph.com\/wp-content\/uploads\/2018\/05\/how-dags-will-solve-the-blokchain-scalability-problem.jpg<\/figcaption><\/figure>\n<p>Bildi\u011fimiz gibi uygulamalar\u0131m\u0131za bu kabiliyetleri kazand\u0131rabilmek i\u00e7in, bir \u00e7ok teknoloji ve mimarilerden yararlan\u0131yoruz. Microservice yakla\u015f\u0131m\u0131 ile <strong>scalable<\/strong>, <strong>resilient<\/strong> ve <strong>lightweight<\/strong> uygulamalar geli\u015ftiriyor, response s\u00fcrelerini minimize edebilmek i\u00e7in de farkl\u0131 caching teknolojilerinden faydalanmaya \u00e7al\u0131\u015f\u0131yoruz.<\/p>\n<p>Peki, bu kadar mimari boyutta uygulamalar\u0131m\u0131za bir \u015feyler kazand\u0131rabilmek i\u00e7in u\u011fra\u015f\u0131rken, baz\u0131 durumlarda neden kod&#8217;lar\u0131m\u0131z\u0131, thread&#8217;lerimizi blokluyoruz?<\/p>\n<p>Unutmamal\u0131y\u0131z ki mimari boyutta uygulamalar\u0131m\u0131za bir \u015feyler kazand\u0131rmaya \u00e7al\u0131\u015ft\u0131\u011f\u0131m\u0131z kadar, kod boyutunda yapt\u0131klar\u0131m\u0131z da bi o kadar \u00f6nemlidir.<\/p>\n<p>Baz\u0131 durumlarda procedural programlama paradigmas\u0131 mant\u0131\u011f\u0131ndan farkl\u0131 olarak, yani kod sat\u0131rlar\u0131ndaki ak\u0131\u015flar\u0131n s\u0131ras\u0131yla takip edilmesi yerine, event-based programlama mant\u0131\u011f\u0131nda hareket etmeli ve uygulamalar\u0131m\u0131z\u0131 <strong>reactive<\/strong> bir hale getirmeliyiz.<\/p>\n<h2>En b\u00fcy\u00fck yard\u0131mc\u0131m\u0131z, Reactive Extensions (Rx)!<\/h2>\n<p>Rx&#8217;i, k\u0131saca hat\u0131rlayal\u0131m.<\/p>\n<p>Rx i\u00e7in k\u0131saca, <strong>observable stream&#8217;leri<\/strong>\u00a0kullanarak push-based, asynchronous ve daha <strong>responsive<\/strong> uygulamalar geli\u015ftirebilmemize olanak sa\u011flayan g\u00fc\u00e7l\u00fc bir library&#8217;dir diyebiliriz.<\/p>\n<figure id=\"attachment_3200\" aria-describedby=\"caption-attachment-3200\" style=\"width: 2500px\" class=\"wp-caption aligncenter\"><a href=\"\/wp-content\/uploads\/2020\/02\/reactive.jpg\"><img decoding=\"async\" class=\"wp-image-3200 size-full lazyload\" data-src=\"\/wp-content\/uploads\/2020\/02\/reactive.jpg\" alt=\"\" width=\"2500\" height=\"1308\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive.jpg 2500w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-300x157.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-1024x536.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-768x402.jpg 768w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-1536x804.jpg 1536w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-2048x1072.jpg 2048w\" data-sizes=\"(max-width: 2500px) 100vw, 2500px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 2500px; --smush-placeholder-aspect-ratio: 2500\/1308;\" \/><\/a><figcaption id=\"caption-attachment-3200\" class=\"wp-caption-text\">https:\/\/blog.westagilelabs.com\/wp-content\/uploads\/2019\/08\/EW17646-2.jpg<\/figcaption><\/figure>\n<p>Rx, complex business logic&#8217;lerini daha basit bir halde ve ayr\u0131ca asynchronous olarak kolay bir \u015fekilde handle edebilmemizi sa\u011flamaktad\u0131r. Ayr\u0131ca Rx, bir \u00e7o\u011fumuzun bildi\u011fi gibi yeni bir konsept olmamakla beraber, temelinde <em>Observer<\/em> design pattern konsept&#8217;i bulunmaktad\u0131r.<\/p>\n<p>Kullan\u0131m senaryolar\u0131n\u0131 ise, genel olarak a\u015fa\u011f\u0131daki gibi s\u0131ralayabiliriz.<\/p>\n<ul>\n<li>Event-based i\u015flemler. \u00d6zellikle uygulama d\u00fczeyindeki complex business logic&#8217;leri daha kolay bir \u015fekilde handle edebilmek ve request&#8217;lere kar\u015f\u0131 responsive olabilmek i\u00e7in.<\/li>\n<li>Asynchronous stream&#8217;leri s\u00fcrekli consume edebilme.<\/li>\n<li>Concurrent programlama.<\/li>\n<\/ul>\n<p>Bu makale kapsam\u0131nda ise kod&#8217;lar\u0131m\u0131z\u0131 ve thread&#8217;lerimizi blok&#8217;lamadan, <strong>asynchronous<\/strong> ve <strong>event-based<\/strong> interaction&#8217;lar\u0131 uygulamalar\u0131m\u0131z i\u00e7erisinde en basit haliyle nas\u0131l handle edebiliriz senaryosunu cover etmeye \u00e7al\u0131\u015faca\u011f\u0131m.<\/p>\n<h2>Observers<\/h2>\n<p>\u00d6rnek bir uygulamaya ge\u00e7meden \u00f6nce, Rx&#8217;in temel ta\u015flar\u0131n\u0131 olu\u015fturan &#8220;<em>IObservable&lt;T&gt;<\/em>&#8221; ve &#8220;<em>IObserver&lt;T&gt;<\/em>&#8221; interface&#8217;lerinden bahsetmek istiyorum.<\/p>\n<p>Bu harika ikili, t\u0131pk\u0131 &#8220;<em>IEnumerable&lt;T&gt;<\/em>&#8221; and &#8220;<em>IEnumerator&lt;T&gt;<\/em>&#8221; interface&#8217;lerine benzemektedir. Farkl\u0131 olarak <strong>pull-based<\/strong> bir yakla\u015f\u0131m yerine, <strong>push-based<\/strong> bir yakla\u015f\u0131m ile \u00e7al\u0131\u015fmaktad\u0131r. B\u00f6ylece s\u00fcrekli bir kaynakta data var m\u0131 diye sormak yerine, ilgili kayna\u011fa subscribe olarak event&#8217;lere kar\u015f\u0131 daha responsive uygulamalar geli\u015ftirebilmekteyiz.<\/p>\n<p>&#8220;<em>IObservable&lt;T&gt;<\/em>&#8221; interface&#8217;ini, g\u00f6zlemlemek istedi\u011fimiz bir kaynak olarak d\u00fc\u015f\u00fcnebiliriz. \u0130\u00e7erisinde ise &#8220;<em>Subscribe(IObserver&lt;T&gt; observer)<\/em>&#8221; method&#8217;unu bulundurmaktad\u0131r. Ad\u0131ndan da anlayabilece\u011fimiz \u00fczere, &#8220;<em>IObserver&lt;T&gt;<\/em>&#8221; ise g\u00f6zlemcimiz.<\/p>\n<p>Hemen basit bir \u00f6rnek ger\u00e7ekle\u015ftirelim.<\/p>\n<pre class=\"lang:c# decode:true\">using System;\r\nusing System.Reactive.Linq;\r\n\r\nnamespace ReactiveNumbers\r\n{\r\n    class Program\r\n    {\r\n        static void Main(string[] args)\r\n        {\r\n            IObservable&lt;long&gt; numbers = Observable.Interval(TimeSpan.FromSeconds(1));\r\n\r\n            numbers.Subscribe(num =&gt; \r\n            {\r\n                Console.WriteLine(num);\r\n            });\r\n\r\n            Console.ReadKey();\r\n        }\r\n    }\r\n}<\/pre>\n<p>Yukar\u0131daki console uygulamas\u0131na bakarsak, &#8220;<em>IObservable&lt;long&gt;<\/em>&#8221; tipinde her saniye tetiklenecek bir kaynak olu\u015fturduk. Ard\u0131ndan bu kayna\u011fa subscribe olarak, data var oldu\u011fu s\u00fcrece console ekran\u0131na yazd\u0131r\u0131lmas\u0131n\u0131 sa\u011flad\u0131k.<\/p>\n<p>Console \u00e7\u0131kt\u0131s\u0131 ise, a\u015fa\u011f\u0131daki gibi sonsuz bir \u015fekilde olacakt\u0131r.<\/p>\n<pre class=\"lang:default decode:true\">% dotnet run\r\n0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n...\r\n\r\n<\/pre>\n<h2>Subject<\/h2>\n<p>Bir g\u00fcn bizden anl\u0131k bir chat uygulamas\u0131 geli\u015ftirmemiz istedi\u011fini varsayal\u0131m. Ayr\u0131ca chat mesajlar\u0131n\u0131n persistent olmas\u0131 ve bu i\u015flemin son kullan\u0131c\u0131 response s\u00fcrelerini etkilememesi de istenmektedir.<\/p>\n<p>Bu kapsamda, anl\u0131k chat i\u015flemleri i\u00e7in <em>SignalR<\/em> library&#8217;sinden yararlanal\u0131m.<\/p>\n<p>Peki, \u00f6ncelikle a\u015fa\u011f\u0131daki gibi bir <em>ASP.NET Core Web API<\/em> projesi olu\u015ftural\u0131m. Ard\u0131ndan &#8220;<em>SignalR<\/em>&#8221; ve &#8220;<em>System.Reactive<\/em>&#8221; library&#8217;lerini NuGet \u00fczerinden projeye dahil edelim.<\/p>\n<pre class=\"lang:default decode:true\">dotnet new webapi -n MyChat<\/pre>\n<pre class=\"lang:default decode:true\">dotnet add package SignalR\r\ndotnet add package System.Reactive<\/pre>\n<p>\u015eimdi &#8220;<em>Models<\/em>&#8221; isminde bir klas\u00f6r olu\u015ftural\u0131m ve i\u00e7erisinde &#8220;<em>ChatMessageReceivedEvent<\/em>&#8221; ad\u0131nda bir event model&#8217;i tan\u0131mlayal\u0131m.<\/p>\n<pre class=\"lang:c# decode:true\">namespace MyChat.Models\r\n{\r\n    public class ChatMessageReceivedEvent\r\n    {\r\n        public string Message { get; set; }\r\n    }\r\n}<\/pre>\n<p>Bu event&#8217;i, socket \u00fczerinden bir chat mesaj\u0131 ald\u0131\u011f\u0131m\u0131zda publish edece\u011fiz. B\u00f6ylece non-blocking, event-based bir chat uygulamas\u0131 geli\u015ftirmeye \u00e7al\u0131\u015faca\u011f\u0131z.<\/p>\n<p>\u015eimdi ise &#8220;<em>Handlers<\/em>&#8221; isminde bir klas\u00f6r olu\u015ftural\u0131m ve i\u00e7erisinde Rx&#8217;i implemente edece\u011fimiz interface&#8217;i a\u015fa\u011f\u0131daki gibi tan\u0131mlayal\u0131m.<\/p>\n<pre class=\"lang:c# decode:true\">using System;\r\nusing MyChat.Models;\r\n\r\nnamespace MyChat.Handlers\r\n{\r\n    public interface IChatEventHandler\r\n    {\r\n        void Publish(ChatMessageReceivedEvent eventMessage);\r\n        void Subscribe(string subscriberName, Action&lt;ChatMessageReceivedEvent&gt; action);\r\n        void Subscribe(string subscriberName, Func&lt;ChatMessageReceivedEvent, bool&gt; predicate, Action&lt;ChatMessageReceivedEvent&gt; action);\r\n    }\r\n}<\/pre>\n<p>Tan\u0131mlam\u0131\u015f oldu\u011fumuz &#8220;<em>Publish<\/em>&#8221; method&#8217;u ile, Rx stream&#8217;ine bir event g\u00f6nderece\u011fiz. Ard\u0131ndan &#8220;<em>Subscribe<\/em>&#8221; method&#8217;u ile de, Rx stream&#8217;ine diledi\u011fimiz bir action&#8217;\u0131 ekleyece\u011fiz.<\/p>\n<p>\u015eimdi a\u015fa\u011f\u0131daki gibi &#8220;<em>Handlers\/Implementations<\/em>&#8221; klas\u00f6r\u00fc alt\u0131nda implementation i\u015flemini ger\u00e7ekle\u015ftirelim.<\/p>\n<pre class=\"lang:c# decode:true\">using System;\r\nusing System.Collections.Generic;\r\nusing System.Reactive.Linq;\r\nusing System.Reactive.Subjects;\r\nusing MyChat.Models;\r\n\r\nnamespace MyChat.Handlers.Implementations\r\n{\r\n    public class ChatEventHandler : IChatEventHandler, IDisposable\r\n    {\r\n        private readonly Subject&lt;ChatMessageReceivedEvent&gt; _subject;\r\n        private readonly Dictionary&lt;string, IDisposable&gt; _subscribers;\r\n\r\n        public ChatEventHandler()\r\n        {\r\n            _subject = new Subject&lt;ChatMessageReceivedEvent&gt;();\r\n            _subscribers = new Dictionary&lt;string, IDisposable&gt;();\r\n        }\r\n\r\n        public void Publish(ChatMessageReceivedEvent eventMessage)\r\n        {\r\n            _subject.OnNext(eventMessage);\r\n        }\r\n\r\n        public void Subscribe(string subscriberName, Action&lt;ChatMessageReceivedEvent&gt; action)\r\n        {\r\n            if (!_subscribers.ContainsKey(subscriberName))\r\n            {\r\n                _subscribers.Add(subscriberName, _subject.Subscribe(action));\r\n            }\r\n        }\r\n\r\n        public void Subscribe(string subscriberName, Func&lt;ChatMessageReceivedEvent, bool&gt; predicate, Action&lt;ChatMessageReceivedEvent&gt; action)\r\n        {\r\n            if (!_subscribers.ContainsKey(subscriberName))\r\n            {\r\n                _subscribers.Add(subscriberName, _subject.Where(predicate).Subscribe(action));\r\n            }\r\n        }\r\n\r\n        public void Dispose()\r\n        {\r\n            if (_subject != null)\r\n            {\r\n                _subject.Dispose();\r\n            }\r\n\r\n            foreach (var subscriber in _subscribers)\r\n            {\r\n                subscriber.Value.Dispose();\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>Dikkat edersek burada, &#8220;<em>IObservable&lt;T&gt;<\/em>&#8221; yerine &#8220;<em>Subject<\/em>&#8221; class&#8217;\u0131n\u0131 kulland\u0131k. \u00c7\u00fcnk\u00fc bu harika class, hem &#8220;<em>IObservable&lt;T&gt;<\/em>&#8221; hem de &#8220;<em>IObserver&lt;T&gt;<\/em>&#8221; \u0131 implemente etmektedir ve bir proxy gibi davranmaktad\u0131r.<\/p>\n<p>&#8220;<em>Publish<\/em>&#8221; method&#8217;unda ise, stream i\u00e7erisinde yeni bir event ger\u00e7ekle\u015fti\u011finde &#8220;<em>Subject<\/em>&#8221; class&#8217;\u0131n\u0131n t\u00fcm subscriber&#8217;lar\u0131 bilgilendirece\u011fi bir observable contract&#8217;\u0131 olan &#8220;<em>OnNext<\/em>&#8221; method&#8217;unu implemente ettik.<\/p>\n<p>Bu ak\u0131\u015f\u0131 g\u00f6rselle\u015ftirdi\u011fimizde ise, a\u015fa\u011f\u0131daki gibi g\u00f6r\u00fcnecektir.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2020\/02\/rx-stream.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-3205 lazyload\" data-src=\"\/wp-content\/uploads\/2020\/02\/rx-stream.jpg\" alt=\"\" width=\"1466\" height=\"481\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-stream.jpg 1466w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-stream-300x98.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-stream-1024x336.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-stream-768x252.jpg 768w\" data-sizes=\"(max-width: 1466px) 100vw, 1466px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1466px; --smush-placeholder-aspect-ratio: 1466\/481;\" \/><\/a><\/p>\n<p>&#8220;<em>Subscribe<\/em>&#8221; method&#8217;u i\u00e7erisinde ise, Rx stream&#8217;ine subscribe olma i\u015flemini ger\u00e7ekle\u015ftiriyoruz. Rx&#8217;in en sevdi\u011fim taraf\u0131 ise, Linq operasyonlar\u0131n\u0131 da destekliyor olmas\u0131.<\/p>\n<p>Unsubscribe i\u015flemini ger\u00e7ekle\u015ftirebilmemiz i\u00e7in ise, subscribe olma i\u015flemi geriye bir &#8220;<em>IDisposable&#8221; <\/em>d\u00f6nmektedir<em>.<\/em> &#8220;<em>Dispose<\/em>&#8221; method&#8217;u i\u00e7erisinde ise, dictionary&#8217;e eklemi\u015f oldu\u011fumuz subscriber&#8217;lar\u0131n unsubscribe i\u015flemlerini ger\u00e7ekle\u015ftiriyoruz. Bu konu hakk\u0131ndaki detayl\u0131 bilgiye ise, <em><a href=\"http:\/\/introtorx.com\/Content\/v1.0.10621.0\/03_LifetimeManagement.html\" target=\"_blank\" rel=\"noopener noreferrer\">buradan<\/a><\/em> ula\u015fabilirsiniz.<\/p>\n<p>\u015eimdi chat k\u0131sm\u0131na ge\u00e7ebiliriz.<\/p>\n<p>Bunun i\u00e7in, &#8220;<em>Hubs<\/em>&#8221; isminde bir klas\u00f6r olu\u015fturarak i\u00e7erisinde &#8220;<em>ChatHub<\/em>&#8221; isminde bir class tan\u0131mlayal\u0131m ve a\u015fa\u011f\u0131daki gibi implemente edelim.<\/p>\n<pre class=\"lang:c# decode:true\">using System.Threading.Tasks;\r\nusing Microsoft.AspNetCore.SignalR;\r\nusing MyChat.Handlers;\r\nusing MyChat.Models;\r\n\r\nnamespace MyChat.Hubs\r\n{\r\n    public class ChatHub : Hub\r\n    {\r\n        private readonly IChatEventHandler _chatEventHandler;\r\n\r\n        public ChatHub(IChatEventHandler chatEventHandler)\r\n        {\r\n            _chatEventHandler = chatEventHandler;\r\n        }\r\n\r\n        public async Task SendMessage(string sender, string message)\r\n        {\r\n            await Clients.All.SendAsync(\"chat\", sender, message);\r\n\r\n            _chatEventHandler.Publish(new ChatMessageReceivedEvent\r\n            {\r\n                Message = message\r\n            });\r\n        }\r\n    }\r\n}<\/pre>\n<p>Burada basit olarak &#8220;<em>SignalR<\/em>&#8221; library&#8217;sinin &#8220;<em>Hub<\/em>&#8221; class&#8217;\u0131n\u0131 inherit alarak, chat i\u00e7in socket \u00fczerinden kullanaca\u011f\u0131m\u0131z &#8220;<em>SendMessage<\/em>&#8221; method&#8217;unu tan\u0131mlad\u0131k.<\/p>\n<p>Ayr\u0131ca son kullan\u0131c\u0131n\u0131n g\u00f6nderdi\u011fi mesajlar\u0131, son kullan\u0131c\u0131n\u0131n response s\u00fcresini etkilemeden persistent bir hale getirebilmek i\u00e7in, &#8220;<em>IChatEventHandler<\/em>&#8221; arac\u0131l\u0131\u011f\u0131yla bir observable stream haline \u00e7eviriyoruz.<\/p>\n<p>Her bir mesaj publish edildi\u011finde ise, Rx stream&#8217;i i\u00e7erisindeki &#8220;<em>OnNext<\/em>&#8221; method&#8217;u \u00e7a\u011f\u0131r\u0131lacak ve ilgili t\u00fcm subscriber&#8217;lar bu event&#8217;ten haberdar edilecektir.<\/p>\n<p>\u015eimdi chat mesajlar\u0131n\u0131 persist edebilmek i\u00e7in, Rx stream&#8217;ine &#8220;<em>ChatHistoryConsumer<\/em>&#8221; ad\u0131nda &#8220;<em>Handlers\/Implementations<\/em>&#8221; path&#8217;i alt\u0131na a\u015fa\u011f\u0131daki gibi bir observer subscribe edelim.<\/p>\n<pre class=\"lang:c# decode:true\">using System.Threading;\r\nusing System.Threading.Tasks;\r\nusing Microsoft.Extensions.Hosting;\r\nusing MyChat.Models;\r\n\r\nnamespace MyChat.Handlers.Implementations\r\n{\r\n    public class ChatHistoryConsumer : BackgroundService\r\n    {\r\n        private readonly IChatEventHandler _eventHandler;\r\n\r\n        public ChatHistoryConsumer(IChatEventHandler eventHandler)\r\n        {\r\n            _eventHandler = eventHandler;\r\n        }\r\n\r\n        protected override Task ExecuteAsync(CancellationToken stoppingToken)\r\n        {\r\n            _eventHandler.Subscribe(subscriberName: typeof(ChatHistoryConsumer).Name,\r\n                                    action: async (e) =&gt;\r\n                                    {\r\n                                        if (e is ChatMessageReceivedEvent)\r\n                                        {\r\n                                            await PersistChatMessagesToDBAsync((ChatMessageReceivedEvent)e);\r\n                                        }\r\n                                    });\r\n\r\n            return Task.CompletedTask;\r\n        }\r\n\r\n        private async Task PersistChatMessagesToDBAsync(ChatMessageReceivedEvent e)\r\n        {\r\n            await System.Console.Out.WriteLineAsync($\"Chat message received and persisted: {e.Message}\");\r\n        }\r\n    }\r\n}<\/pre>\n<p>Burada ise &#8220;<em>ChatHistoryConsumer<\/em>&#8221; class&#8217;\u0131n\u0131n bir background task&#8217;\u0131 olarak \u00e7al\u0131\u015fabilmesi i\u00e7in, &#8220;<em>BackgroundService<\/em>&#8221; class&#8217;\u0131n\u0131 inherit ederek &#8220;<em>ExecuteAsync<\/em>&#8221; method&#8217;unu implemente ettik.<\/p>\n<p>Ard\u0131ndan &#8220;<em>ExecuteAsync<\/em>&#8221; method&#8217;u i\u00e7erisinde ise, &#8220;<em>ChatMessageReceivedEvent<\/em>&#8221; i\u00e7in subscription i\u015flemini ger\u00e7ekle\u015ftirdik.<\/p>\n<p>\u015eimdi &#8220;<em>Startup<\/em>&#8221; class&#8217;\u0131n\u0131 ise, a\u015fa\u011f\u0131daki gibi g\u00fcncelleyelim.<\/p>\n<pre class=\"lang:c# decode:true\">using Microsoft.AspNetCore.Builder;\r\nusing Microsoft.AspNetCore.Hosting;\r\nusing Microsoft.Extensions.Configuration;\r\nusing Microsoft.Extensions.DependencyInjection;\r\nusing Microsoft.Extensions.Hosting;\r\nusing MyChat.Handlers;\r\nusing MyChat.Handlers.Implementations;\r\nusing MyChat.Hubs;\r\n\r\nnamespace MyChat\r\n{\r\n    public class Startup\r\n    {\r\n        public Startup(IConfiguration configuration)\r\n        {\r\n            Configuration = configuration;\r\n        }\r\n\r\n        public IConfiguration Configuration { get; }\r\n\r\n        \/\/ This method gets called by the runtime. Use this method to add services to the container.\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddRazorPages();\r\n            services.AddControllers();\r\n            services.AddSignalR();\r\n            services.AddSingleton&lt;IChatEventHandler, ChatEventHandler&gt;();\r\n            services.AddHostedService&lt;ChatHistoryConsumer&gt;();\r\n        }\r\n\r\n        \/\/ This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\r\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n        {\r\n            if (env.IsDevelopment())\r\n            {\r\n                app.UseDeveloperExceptionPage();\r\n            }\r\n\r\n            app.UseHttpsRedirection();\r\n            app.UseStaticFiles();\r\n\r\n            app.UseRouting();\r\n\r\n            app.UseAuthorization();\r\n\r\n            app.UseEndpoints(endpoints =&gt;\r\n            {\r\n                endpoints.MapRazorPages();\r\n                endpoints.MapHub&lt;ChatHub&gt;(\"\/hubs\/chat\");\r\n            });\r\n        }\r\n    }\r\n}<\/pre>\n<p>Burada ise chat uygulamalas\u0131n\u0131 test edebilmek i\u00e7in, <em>Razor Pages<\/em>&#8216;i ve <em>SignalR<\/em>&#8216;\u0131 etkinle\u015ftirdik. Ard\u0131ndan gerekli injection i\u015flemlerini ger\u00e7ekle\u015ftirdik.<\/p>\n<p>\u015eimdi test i\u015flemini yapabilmek i\u00e7in, basit bir <em>UI<\/em> haz\u0131rlayal\u0131m.<\/p>\n<p>\u00d6ncelikle gerekli <em>SignalR<\/em> javascript paketlerini projeye dahil edebilmek i\u00e7in, <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/signalr\/javascript-client?view=aspnetcore-3.1&amp;WT.mc_id=DT-MVP-5003382#install-the-signalr-client-package\" target=\"_blank\" rel=\"noopener noreferrer\">buradaki<\/a><\/em> ilk ad\u0131m\u0131 takip edelim.<\/p>\n<p>Ard\u0131ndan &#8220;<em>Pages<\/em>&#8221; isminde bir klas\u00f6r olu\u015fturarak, i\u00e7erisinde &#8220;<em>Chat<\/em>&#8221; ad\u0131nda a\u015fa\u011f\u0131daki gibi bir <em>Razor Page<\/em> olu\u015ftural\u0131m.<\/p>\n<pre class=\"lang:xhtml decode:true\">@page\r\n\r\n&lt;style&gt;\r\ninput[type=text] {\r\n  width: 100%;\r\n  padding: 12px 20px;\r\n  margin: 8px 0;\r\n  box-sizing: border-box;\r\n}\r\n&lt;\/style&gt;\r\n\r\n&lt;div&gt;\r\n    &lt;h2&gt;Chat Test&lt;\/h2&gt;\r\n    &lt;div&gt;\r\n        &lt;ul id=\"messageList\"&gt;&lt;\/ul&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n&lt;div&gt;\r\n    &lt;div&gt;Sender: &lt;input type=\"text\" id=\"sender\"\/&gt;&lt;\/div&gt;\r\n    &lt;div&gt;Message: &lt;input type=\"text\" id=\"message\"\"&gt;&lt;\/div&gt;\r\n    &lt;div&gt;&lt;input type=\"button\" id=\"sendMessage\" value=\"Send\" \/&gt;&lt;\/div&gt;\r\n&lt;\/div&gt;\r\n\r\n&lt;script src=\"\/lib\/signalr\/signalr.js\"&gt;&lt;\/script&gt;\r\n&lt;script src=\"\/lib\/signalr\/chat.js\"&gt;&lt;\/script&gt;<\/pre>\n<p><em>SignalR<\/em> javascript client&#8217;\u0131n\u0131 ise, &#8220;<em>chat.js<\/em>&#8221; ad\u0131yla &#8220;<em>wwwroot\/lib\/signalr<\/em>&#8221; klas\u00f6r path&#8217;i alt\u0131nda a\u015fa\u011f\u0131daki gibi olu\u015ftural\u0131m.<\/p>\n<pre class=\"lang:js decode:true  \">const connection = new signalR.HubConnectionBuilder()\r\n    .withUrl(\"https:\/\/localhost:5001\/hubs\/chat\")\r\n    .build();\r\n\r\ndocument.getElementById(\"sendMessage\").addEventListener(\"click\", event =&gt; {\r\n    const message = document.getElementById(\"message\").value;\r\n    const sender = document.getElementById(\"sender\").value;\r\n\r\n    connection.invoke(\"SendMessage\", sender, message).catch(err =&gt; console.error(err.toString()));\r\n    event.preventDefault();\r\n});\r\n\r\nconnection.on(\"chat\", (sender, message) =&gt; {\r\n    const recMessage = sender + \": \" + message;\r\n    const li = document.createElement(\"li\");\r\n\r\n    li.textContent = recMessage;\r\n    document.getElementById(\"messageList\").appendChild(li);\r\n});\r\n\r\nconnection.start().catch(err =&gt; console.error(err.toString()));<\/pre>\n<p>Burada ise olu\u015fturmu\u015f oldu\u011fumuz &#8220;<em>ChatHub<\/em>&#8221; a socket \u00fczerinden ba\u011flanacak ve mesaj g\u00f6nderilebilecek basit bir <em>UI<\/em> haz\u0131rlad\u0131k.<\/p>\n<p>\u015eimdi test i\u015flemine ge\u00e7ebiliriz.<\/p>\n<p>Test edebilmek i\u00e7in uygulamay\u0131 &#8220;<em>dotnet run<\/em>&#8221; komutu ile \u00e7al\u0131\u015ft\u0131ral\u0131m ve iki farkl\u0131 browser \u00fczerinden a\u015fa\u011f\u0131daki gibi chat i\u015flemini ger\u00e7ekle\u015ftirelim.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2020\/02\/rx-result2.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-3212 lazyload\" data-src=\"\/wp-content\/uploads\/2020\/02\/rx-result2.jpg\" alt=\"\" width=\"1064\" height=\"789\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-result2.jpg 1064w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-result2-300x222.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-result2-1024x759.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/rx-result2-768x570.jpg 768w\" data-sizes=\"(max-width: 1064px) 100vw, 1064px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1064px; --smush-placeholder-aspect-ratio: 1064\/789;\" \/><\/a><\/p>\n<p>Yukar\u0131daki console ekran\u0131na dikkat edersek, biz chat i\u015flemini ger\u00e7ekle\u015ftirirken olu\u015fturmu\u015f oldu\u011fumuz observer ise, mesajlar\u0131n persist edilme i\u015flemini non-blocking ve asynchronous bir \u015fekilde ger\u00e7ekle\u015ftirmi\u015ftir.<\/p>\n<p>Rx yakla\u015f\u0131m\u0131n\u0131n g\u00fczel olan taraf\u0131 ise, yeni bir \u00f6zellik eklenilmesi istendi\u011finde business logic&#8217;leri kompleks bir hale getirmeden bu de\u011fi\u015fikliklere izin vermesi. \u00d6rne\u011fin, chat mesajlar\u0131 i\u00e7erisinde k\u00f6t\u00fc kelimelere kar\u015f\u0131 filtreleme yap\u0131lmas\u0131 \u00f6zelli\u011finin istendi\u011fini d\u00fc\u015f\u00fcnebiliriz. Tek yapmam\u0131z gereken, ilgili Rx stream&#8217;ine yeni bir observer daha eklemek olacakt\u0131r.<\/p>\n<p>GitHub: <a href=\"https:\/\/github.com\/GokGokalp\/dotnetcore-reactive-extensions\" target=\"_blank\" rel=\"noopener noreferrer\"><em>https:\/\/github.com\/GokGokalp\/dotnetcore-reactive-extensions<\/em><\/a><\/p>\n<h2>Referanslar<\/h2>\n<blockquote>\n<p><em>docs.microsoft.com\/en-us\/dotnet\/api\/system.iobservable-1?view=netframework-4.7.2&amp;WT.mc_id=DT-MVP-5003382<br \/><\/em><em>dotnetcorecentral.com\/blog\/reactive-extensions-in-net-core\/<br \/>docs.microsoft.com\/en-us\/previous-versions\/dotnet\/reactive-extensions\/hh242974%28v%3dvs.103%29?WT.mc_id=DT-MVP-5003382<\/em><\/p>\n<\/blockquote>\n<p>\n","protected":false},"excerpt":{"rendered":"<p>Eskiden sadece belirli bir kesime hitap eden uygulamalar geli\u015ftirirken, g\u00fcn\u00fcm\u00fcz teknoloji \u00e7a\u011f\u0131n\u0131n ilerlemesiyle ve global marketten de bir pay alabilmek i\u00e7in, art\u0131k daha b\u00fcy\u00fck bir kesime hitap eden uygulamalar geli\u015ftirmemiz gerekiyor. Geli\u015ftirdi\u011fimiz uygulamalar\u0131n 7\/24 kesintisiz hizmet verebiliyor olmas\u0131 ve response s\u00fcreleri d\u00fc\u015f\u00fck olan, kullan\u0131c\u0131 deneyimi&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/gokhan-gokalp.com\/tr\/asp-net-core-series-05-dont-block-your-code-be-reactive\/\">Devam\u0131n\u0131 okuyun<span class=\"screen-reader-text\">ASP.NET Core Serisi 05: Kod&#8217;unu bloklama, reactive ol<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":3308,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[505,417,231],"tags":[566,567,565,564,561,562,563],"class_list":["post-3169","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-asp-net-core","category-refactoring","tag-asp-net-core-reactive","tag-observables","tag-reactive-c","tag-reactive-extension","tag-reactive-programming","tag-rx","tag-rx-net","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"tr","enabled_languages":["en","tr"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"tr":{"title":true,"content":true,"excerpt":false}}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>ASP.NET Core Serisi 05: Kod&#039;unu bloklama, reactive ol - G\u00f6khan G\u00f6kalp<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ASP.NET Core Serisi 05: Kod&#039;unu bloklama, reactive ol - G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/\" \/>\n<meta property=\"og:site_name\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"article:published_time\" content=\"2020-02-27T16:06:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-03-02T09:12:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-featured-image.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/\"},\"author\":{\"name\":\"G\u00f6khan G\u00f6kalp\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"headline\":\"ASP.NET Core Serisi 05: Kod&#8217;unu bloklama, reactive ol\",\"datePublished\":\"2020-02-27T16:06:15+00:00\",\"dateModified\":\"2020-03-02T09:12:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/\"},\"wordCount\":2825,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/reactive-featured-image.jpg\",\"keywords\":[\"asp.net core reactive\",\"observables\",\"reactive c#\",\"reactive extension\",\"reactive programming\",\"rx\",\"rx.net\"],\"articleSection\":[\".NET Core\",\"ASP.NET Core\",\"Refactoring\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/\",\"name\":\"ASP.NET Core Serisi 05: Kod'unu bloklama, reactive ol - G\u00f6khan G\u00f6kalp\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/reactive-featured-image.jpg\",\"datePublished\":\"2020-02-27T16:06:15+00:00\",\"dateModified\":\"2020-03-02T09:12:21+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#primaryimage\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/reactive-featured-image.jpg\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/reactive-featured-image.jpg\",\"width\":1200,\"height\":675},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/asp-net-core-series-05-dont-block-your-code-be-reactive\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"ASP.NET Core Series 05: Don&#8217;t block your code, be reactive\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"description\":\"C# &amp; Python lover\",\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gokhan-gokalp.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"pronouns\":\"he\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\"},\"sameAs\":[\"https:\\\/\\\/gokhan-gokalp.com\"],\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/tr\\\/author\\\/gok-gokalp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"ASP.NET Core Serisi 05: Kod'unu bloklama, reactive ol - G\u00f6khan G\u00f6kalp","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/","og_locale":"tr_TR","og_type":"article","og_title":"ASP.NET Core Serisi 05: Kod'unu bloklama, reactive ol - G\u00f6khan G\u00f6kalp","og_url":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/","og_site_name":"G\u00f6khan G\u00f6kalp","article_published_time":"2020-02-27T16:06:15+00:00","article_modified_time":"2020-03-02T09:12:21+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-featured-image.jpg","type":"image\/jpeg"}],"author":"G\u00f6khan G\u00f6kalp","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"G\u00f6khan G\u00f6kalp","Tahmini okuma s\u00fcresi":"20 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#article","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/"},"author":{"name":"G\u00f6khan G\u00f6kalp","@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"headline":"ASP.NET Core Serisi 05: Kod&#8217;unu bloklama, reactive ol","datePublished":"2020-02-27T16:06:15+00:00","dateModified":"2020-03-02T09:12:21+00:00","mainEntityOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/"},"wordCount":2825,"commentCount":4,"publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-featured-image.jpg","keywords":["asp.net core reactive","observables","reactive c#","reactive extension","reactive programming","rx","rx.net"],"articleSection":[".NET Core","ASP.NET Core","Refactoring"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/","url":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/","name":"ASP.NET Core Serisi 05: Kod'unu bloklama, reactive ol - G\u00f6khan G\u00f6kalp","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#primaryimage"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-featured-image.jpg","datePublished":"2020-02-27T16:06:15+00:00","dateModified":"2020-03-02T09:12:21+00:00","breadcrumb":{"@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/"]}]},{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#primaryimage","url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-featured-image.jpg","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2020\/02\/reactive-featured-image.jpg","width":1200,"height":675},{"@type":"BreadcrumbList","@id":"https:\/\/gokhan-gokalp.com\/asp-net-core-series-05-dont-block-your-code-be-reactive\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gokhan-gokalp.com\/"},{"@type":"ListItem","position":2,"name":"ASP.NET Core Series 05: Don&#8217;t block your code, be reactive"}]},{"@type":"WebSite","@id":"https:\/\/gokhan-gokalp.com\/#website","url":"https:\/\/gokhan-gokalp.com\/","name":"G\u00f6khan G\u00f6kalp","description":"C# &amp; Python lover","publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gokhan-gokalp.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe","name":"G\u00f6khan G\u00f6kalp","pronouns":"he","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659"},"sameAs":["https:\/\/gokhan-gokalp.com"],"url":"https:\/\/gokhan-gokalp.com\/tr\/author\/gok-gokalp\/"}]}},"_links":{"self":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/3169","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/comments?post=3169"}],"version-history":[{"count":5,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/3169\/revisions"}],"predecessor-version":[{"id":3314,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/3169\/revisions\/3314"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media\/3308"}],"wp:attachment":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media?parent=3169"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/categories?post=3169"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/tags?post=3169"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}