{"id":34045,"date":"2025-11-10T10:31:18","date_gmt":"2025-11-10T07:31:18","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/"},"modified":"2025-11-10T10:31:18","modified_gmt":"2025-11-10T07:31:18","slug":"signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/","title":{"rendered":"SignalR ile .NET Core &#038; Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi"},"content":{"rendered":"<p><body><\/p>\n<p>Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve Angular gibi g\u00fc\u00e7l\u00fc teknolojileri SignalR ile birle\u015ftirerek ger\u00e7ek zamanl\u0131 g\u00fcncellemeleri nas\u0131l sa\u011flayabiliriz? Bu makale, sunucudan istemciye sorunsuz veri ak\u0131\u015f\u0131 sa\u011flama s\u00fcrecini ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.<\/p>\n<p>G\u00fcn\u00fcm\u00fcz\u00fcn dinamik d\u00fcnyas\u0131nda, kullan\u0131c\u0131lar\u0131n uygulamalarla etkile\u015fim beklentileri hi\u00e7 olmad\u0131\u011f\u0131 kadar y\u00fcksek. Geleneksel web uygulamalar\u0131, kullan\u0131c\u0131n\u0131n bir eylemde bulunmas\u0131n\u0131 (sayfay\u0131 yenileme, bir butona t\u0131klama) bekleyerek sunucudan veri \u00e7eker. Bu y\u00f6ntem, statik i\u00e7erikler veya nadiren g\u00fcncellenen veriler i\u00e7in yeterli olsa da, anl\u0131k de\u011fi\u015fimlerin oldu\u011fu senaryolarda yetersiz kal\u0131r. \u00d6rne\u011fin, bir \u00e7evrimi\u00e7i sohbet uygulamas\u0131nda her mesaj i\u00e7in sayfay\u0131 yenilemek veya bir hisse senedi takip uygulamas\u0131nda her fiyat de\u011fi\u015fimi i\u00e7in manuel g\u00fcncelleme yapmak hem kullan\u0131c\u0131 deneyimini k\u00f6t\u00fcle\u015ftirir hem de gereksiz sunucu y\u00fck\u00fc olu\u015fturur.<\/p>\n<p>\u0130\u015fte tam da bu noktada, ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131 \u00e7\u00f6z\u00fcmleri devreye giriyor. Anl\u0131k bildirimler, canl\u0131 sohbetler, borsa takibi, spor m\u00fcsabakas\u0131 skorlar\u0131, \u00e7ok kullan\u0131c\u0131l\u0131 oyunlar veya interaktif dashboard&#8217;lar gibi uygulamalar, sunucudan istemciye an\u0131nda ve otomatik veri iletimine ihtiya\u00e7 duyar. Bu sayede kullan\u0131c\u0131lar, en g\u00fcncel bilgilere an\u0131nda eri\u015febilir, karar alma s\u00fcre\u00e7lerini h\u0131zland\u0131rabilir ve \u00e7ok daha ak\u0131c\u0131 bir deneyim ya\u015fayabilirler. Bu t\u00fcr bir ileti\u015fim modeli, uygulaman\u0131z\u0131n etkile\u015fimini ve yan\u0131t verme h\u0131z\u0131n\u0131 \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131r\u0131r. Geleneksel HTTP request-response modelinin aksine, ger\u00e7ek zamanl\u0131 sistemler, sunucunun istemcilere proaktif olarak bilgi g\u00f6ndermesini sa\u011flar. Bu, \u00f6zellikle veri hacminin y\u00fcksek oldu\u011fu ve g\u00fcncellemelerin s\u0131k oldu\u011fu durumlarda performans\u0131 ve verimlili\u011fi art\u0131r\u0131r.<\/p>\n<p>Bu gereksinimleri kar\u015f\u0131lamak i\u00e7in geli\u015ftirilen teknolojilerden biri de <strong>SignalR<\/strong>&#8216;d\u0131r. SignalR, .NET ekosisteminde ger\u00e7ek zamanl\u0131 web i\u015flevselli\u011fi eklemek i\u00e7in g\u00fc\u00e7l\u00fc ve kullan\u0131m\u0131 kolay bir k\u00fct\u00fcphanedir. WebSockets, Server-Sent Events ve Long Polling gibi farkl\u0131 transport mekanizmalar\u0131n\u0131 otomatik olarak y\u00f6neterek, geli\u015ftiricilerin taray\u0131c\u0131lar ve sunucular aras\u0131nda kesintisiz, iki y\u00f6nl\u00fc ileti\u015fimi kolayca kurmas\u0131n\u0131 sa\u011flar. .NET Core&#8217;un mod\u00fcler yap\u0131s\u0131yla birle\u015fti\u011finde, SignalR modern, y\u00fcksek performansl\u0131 ve \u00f6l\u00e7eklenebilir ger\u00e7ek zamanl\u0131 uygulamalar geli\u015ftirmek i\u00e7in ideal bir \u00e7\u00f6z\u00fcm haline gelir. Bu makalede, .NET Core backend&#8217;i ve Angular frontend&#8217;i kullanarak SignalR ile nas\u0131l ger\u00e7ek zamanl\u0131 veri g\u00fcncellemeleri yapaca\u011f\u0131m\u0131z\u0131 ad\u0131m ad\u0131m inceleyece\u011fiz. B\u00f6ylece, kullan\u0131c\u0131lar\u0131n\u0131za sadece bilgi de\u011fil, ayn\u0131 zamanda anl\u0131k, dinamik ve s\u00fcr\u00fckleyici bir deneyim sunabileceksiniz.<\/p>\n<h2>SignalR Nedir ve Temelleri Nelerdir?<\/h2>\n<p>SignalR, Microsoft taraf\u0131ndan geli\u015ftirilen ve ASP.NET Core uygulamalar\u0131n\u0131za ger\u00e7ek zamanl\u0131 web i\u015flevselli\u011fi eklemenizi sa\u011flayan a\u00e7\u0131k kaynakl\u0131 bir k\u00fct\u00fcphanedir. Peki, bu tam olarak ne anlama geliyor ve nas\u0131l \u00e7al\u0131\u015f\u0131yor? Temel olarak, SignalR sunucunuzun ba\u011fl\u0131 istemcilere (web taray\u0131c\u0131lar\u0131, mobil uygulamalar vb.) an\u0131nda veri g\u00f6ndermesini m\u00fcmk\u00fcn k\u0131lar. Geleneksel HTTP istek-yan\u0131t modeli, istemcinin bir istek g\u00f6ndermesini ve sunucunun buna yan\u0131t vermesini gerektirirken, SignalR sunucunun istemcilere aktif olarak &#8220;push&#8221; yapmas\u0131na olanak tan\u0131r.<\/p>\n<p>SignalR&#8217;\u0131n en b\u00fcy\u00fck avantajlar\u0131ndan biri, farkl\u0131 transport mekanizmalar\u0131n\u0131 otomatik olarak y\u00f6netmesidir. Yani geli\u015ftiricilerin WebSockets, Server-Sent Events veya Long Polling gibi teknolojilerle u\u011fra\u015fmas\u0131na gerek kalmaz. SignalR, ba\u011flant\u0131 kurmaya \u00e7al\u0131\u015f\u0131rken istemci ve sunucunun yeteneklerine g\u00f6re en iyi transport y\u00f6ntemini otomatik olarak se\u00e7er. E\u011fer WebSockets destekleniyorsa, bu en verimli y\u00f6ntem tercih edilir; aksi takdirde, daha eski taray\u0131c\u0131lar i\u00e7in Server-Sent Events veya Long Polling kullan\u0131l\u0131r. Bu &#8220;d\u00fc\u015fme&#8221; (fall-back) mekanizmas\u0131, uygulaman\u0131z\u0131n geni\u015f bir yelpazedeki cihaz ve taray\u0131c\u0131da \u00e7al\u0131\u015fmas\u0131n\u0131 garanti eder.<\/p>\n<p>SignalR&#8217;\u0131n temel bile\u015fenleri \u015funlard\u0131r:<\/p>\n<ul>\n<li>\n        <strong>Hub&#8217;lar (Hubs):<\/strong> SignalR&#8217;\u0131n merkezidir. Bir Hub, istemcilerle sunucu aras\u0131ndaki ileti\u015fim kanal\u0131n\u0131 y\u00f6neten bir s\u0131n\u0131ft\u0131r. Hub&#8217;lar \u00fczerinden istemciler sunucudaki metodlar\u0131 \u00e7a\u011f\u0131rabilir (RPC &#8211; Remote Procedure Call), sunucu da ba\u011fl\u0131 istemcilerdeki metodlar\u0131 \u00e7a\u011f\u0131rabilir. \u00d6rne\u011fin, bir sohbet uygulamas\u0131nda, bir Hub &#8220;mesaj g\u00f6nder&#8221; veya &#8220;mesaj al&#8221; gibi i\u015flevleri i\u00e7erebilir. Hub&#8217;lar genellikle t\u00fcretildi\u011fi <code>Hub<\/code> s\u0131n\u0131f\u0131ndan miras al\u0131n\u0131r.\n    <\/li>\n<li>\n        <strong>\u0130stemciler (Clients):<\/strong> Sunucuya ba\u011fl\u0131 olan taray\u0131c\u0131lar, masa\u00fcst\u00fc uygulamalar\u0131 veya mobil cihazlard\u0131r. \u0130stemciler, SignalR client k\u00fct\u00fcphanelerini kullanarak Hub&#8217;a ba\u011flan\u0131r, Hub metodlar\u0131n\u0131 \u00e7a\u011f\u0131r\u0131r ve Hub&#8217;dan gelen mesajlar\u0131 dinler. JavaScript, TypeScript (Angular i\u00e7in), .NET, Java gibi bir\u00e7ok dilde istemci k\u00fct\u00fcphaneleri bulunur.\n    <\/li>\n<li>\n        <strong>Ba\u011flant\u0131lar (Connections):<\/strong> Bir istemci ile Hub aras\u0131nda kurulan kal\u0131c\u0131 ba\u011flant\u0131d\u0131r. Bu ba\u011flant\u0131, verinin iki y\u00f6nl\u00fc ak\u0131\u015f\u0131n\u0131 sa\u011flar. SignalR, ba\u011flant\u0131n\u0131n kesilmesi durumunda otomatik yeniden ba\u011flant\u0131 kurma yetene\u011fine de sahiptir, bu da uygulamalar\u0131n daha kararl\u0131 olmas\u0131n\u0131 sa\u011flar.\n    <\/li>\n<\/ul>\n<p>SignalR&#8217;\u0131n \u00e7al\u0131\u015fma prensibi olduk\u00e7a basittir: \u0130stemci bir SignalR Hub&#8217;\u0131na ba\u011flan\u0131r. Ba\u011flant\u0131 kurulduktan sonra, istemci sunucudaki Hub metodlar\u0131n\u0131 \u00e7a\u011f\u0131rabilir. Ayn\u0131 \u015fekilde, sunucu da Hub arac\u0131l\u0131\u011f\u0131yla belirli bir istemciye, bir istemci grubuna veya t\u00fcm ba\u011fl\u0131 istemcilere veri g\u00f6nderebilir. Bu i\u015flem genellikle istemcide tan\u0131mlanm\u0131\u015f JavaScript fonksiyonlar\u0131n\u0131 veya di\u011fer dildeki metodlar\u0131 \u00e7a\u011f\u0131rarak ger\u00e7ekle\u015ftirilir. Bu iki y\u00f6nl\u00fc ileti\u015fim yetene\u011fi, anl\u0131k bildirimler, sohbet odalar\u0131, canl\u0131 veri tablolar\u0131 ve \u00e7ok kullan\u0131c\u0131l\u0131 etkile\u015fimli uygulamalar gibi senaryolar i\u00e7in SignalR&#8217;\u0131 m\u00fckemmel bir se\u00e7im haline getirir.<\/p>\n<div class=\"expert-tip\">\n  <strong>Uzman \u0130pucu:<\/strong> SignalR Hub&#8217;lar\u0131n\u0131z\u0131 k\u00fc\u00e7\u00fck ve odaklanm\u0131\u015f tutmak, kodunuzun daha y\u00f6netilebilir olmas\u0131n\u0131 sa\u011flar. Farkl\u0131 i\u015flevsellikler i\u00e7in ayr\u0131 Hub&#8217;lar olu\u015fturmay\u0131 d\u00fc\u015f\u00fcnebilirsiniz (\u00f6rn. <code>ChatHub<\/code>, <code>NotificationHub<\/code>, <code>DataUpdateHub<\/code>).\n<\/div>\n<h2>.NET Core ile SignalR Sunucusu Nas\u0131l Kurulur?<\/h2>\n<p>\u015eimdi teoriden prati\u011fe ge\u00e7elim ve .NET Core backend&#8217;inizde bir SignalR sunucusunu nas\u0131l yap\u0131land\u0131raca\u011f\u0131n\u0131z\u0131 ad\u0131m ad\u0131m inceleyelim. Bu b\u00f6l\u00fcmde, projenizi olu\u015fturmaktan bir Hub tan\u0131mlamaya ve bunu yap\u0131land\u0131rmaya kadar t\u00fcm s\u00fcreci ele alaca\u011f\u0131z. Amac\u0131m\u0131z, Angular istemcilerimizin ba\u011flanabilece\u011fi ve ger\u00e7ek zamanl\u0131 veri al\u0131\u015fveri\u015fi yapabilece\u011fi basit bir API olu\u015fturmak.<\/p>\n<h3>Ad\u0131m 1: Yeni Bir .NET Core Web API Projesi Olu\u015fturma<\/h3>\n<p>\u00d6ncelikle, Visual Studio veya .NET CLI kullanarak yeni bir ASP.NET Core Web API projesi olu\u015ftural\u0131m. Bu, SignalR Hub&#8217;\u0131m\u0131z\u0131 bar\u0131nd\u0131racak temel yap\u0131m\u0131z olacak.<\/p>\n<pre><code>\ndotnet new webapi -n SignalRDemo.Api\ncd SignalRDemo.Api\n<\/pre>\n<p><\/code><\/p>\n<p>Bu komutlar, <code>SignalRDemo.Api<\/code> ad\u0131nda yeni bir Web API projesi olu\u015fturacak ve proje dizinine ge\u00e7i\u015f yapacakt\u0131r.<\/p>\n<h3>Ad\u0131m 2: SignalR NuGet Paketlerini Kurma<\/h3>\n<p>SignalR i\u015flevselli\u011fini projenize eklemek i\u00e7in gerekli NuGet paketini y\u00fcklemeniz gerekiyor. Genellikle ASP.NET Core projelerinde <code>Microsoft.AspNetCore.SignalR<\/code> paketi kullan\u0131l\u0131r.<\/p>\n<pre><code>\ndotnet add package Microsoft.AspNetCore.SignalR\n<\/pre>\n<p><\/code><\/p>\n<h3>Ad\u0131m 3: Bir SignalR Hub'\u0131 Olu\u015fturma<\/h3>\n<p>\u015eimdi istemcilerimizle ileti\u015fim kuracak Hub s\u0131n\u0131f\u0131n\u0131 olu\u015ftural\u0131m. Proje k\u00f6k dizininde veya uygun bir klas\u00f6rde (\u00f6rn. <code>Hubs<\/code> klas\u00f6r\u00fc alt\u0131nda) yeni bir C# s\u0131n\u0131f\u0131 dosyas\u0131 (\u00f6rn. <code>NotificationHub.cs<\/code>) olu\u015ftural\u0131m.<\/p>\n<pre><code>\n\/\/ Hubs\/NotificationHub.cs\nusing Microsoft.AspNetCore.SignalR;\nusing System.Threading.Tasks;\n\nnamespace SignalRDemo.Api.Hubs\n{\n    public class NotificationHub : Hub\n    {\n        public async Task SendNotification(string user, string message)\n        {\n            \/\/ Ba\u011fl\u0131 t\u00fcm istemcilere \"ReceiveNotification\" metodunu \u00e7a\u011f\u0131r\u0131r.\n            await Clients.All.SendAsync(\"ReceiveNotification\", user, message);\n        }\n\n        public async Task SendNotificationToCaller(string message)\n        {\n            \/\/ Yaln\u0131zca mesaj\u0131 g\u00f6nderen istemciye \"ReceiveNotification\" metodunu \u00e7a\u011f\u0131r\u0131r.\n            await Clients.Caller.SendAsync(\"ReceiveNotification\", \"Server\", message);\n        }\n\n        public override async Task OnConnectedAsync()\n        {\n            \/\/ Yeni bir istemci ba\u011fland\u0131\u011f\u0131nda \u00e7al\u0131\u015f\u0131r.\n            Console.WriteLine($\"Client connected: {Context.ConnectionId}\");\n            await Clients.Caller.SendAsync(\"ReceiveNotification\", \"Server\", $\"Ho\u015f geldiniz, Ba\u011flant\u0131 Kimli\u011finiz: {Context.ConnectionId}\");\n            await base.OnConnectedAsync();\n        }\n\n        public override async Task OnDisconnectedAsync(Exception? exception)\n        {\n            \/\/ Bir istemcinin ba\u011flant\u0131s\u0131 kesildi\u011finde \u00e7al\u0131\u015f\u0131r.\n            Console.WriteLine($\"Client disconnected: {Context.ConnectionId}\");\n            await base.OnDisconnectedAsync(exception);\n        }\n    }\n}\n<\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki \u00f6rnekte, <code>NotificationHub<\/code> s\u0131n\u0131f\u0131 <code>Hub<\/code> s\u0131n\u0131f\u0131ndan miras al\u0131r. <code>SendNotification<\/code> metodu, Hub'a ba\u011fl\u0131 t\u00fcm istemcilere bir mesaj g\u00f6nderirken, <code>SendNotificationToCaller<\/code> sadece \u00e7a\u011fr\u0131y\u0131 yapan istemciye mesaj g\u00f6nderir. <code>OnConnectedAsync<\/code> ve <code>OnDisconnectedAsync<\/code> metodlar\u0131, istemci ba\u011flant\u0131lar\u0131 durumunda tetiklenen ya\u015fam d\u00f6ng\u00fcs\u00fc metodlar\u0131d\u0131r.<\/p>\n<h3>Ad\u0131m 4: Startup.cs (veya Program.cs) Dosyas\u0131n\u0131 Yap\u0131land\u0131rma<\/h3>\n<p>.NET 6 ve sonraki s\u00fcr\u00fcmlerde <code>Program.cs<\/code> dosyas\u0131nda, \u00f6nceki s\u00fcr\u00fcmlerde ise <code>Startup.cs<\/code> dosyas\u0131nda SignalR servislerini ve Hub'\u0131n\u0131z\u0131 uygulaman\u0131za eklemeniz gerekir. Bu, SignalR'\u0131n HTTP pipeline'\u0131na entegre olmas\u0131n\u0131 sa\u011flar.<\/p>\n<h4>.NET 6+ (Minimal API) i\u00e7in Program.cs<\/h4>\n<pre><code>\n\/\/ Program.cs\nusing SignalRDemo.Api.Hubs;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.Extensions.DependencyInjection;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n\/\/ SignalR servislerini ekle\nbuilder.Services.AddSignalR();\nbuilder.Services.AddControllers(); \/\/ E\u011fer API Controller kullan\u0131yorsan\u0131z\nbuilder.Services.AddEndpointsApiExplorer();\nbuilder.Services.AddSwaggerGen();\n\n\/\/ CORS yap\u0131land\u0131rmas\u0131 - Angular uygulaman\u0131z\u0131n farkl\u0131 bir kaynaktan ba\u011flanabilmesi i\u00e7in \u00f6nemli\nbuilder.Services.AddCors(options =>\n{\n    options.AddPolicy(\"CorsPolicy\",\n        builder => builder\n            .WithOrigins(\"http:\/\/localhost:4200\") \/\/ Angular uygulaman\u0131z\u0131n adresi\n            .AllowAnyMethod()\n            .AllowAnyHeader()\n            .AllowCredentials()); \/\/ Kimlik do\u011frulama gerektiren ba\u011flant\u0131lar i\u00e7in\n});\n\nvar app = builder.Build();\n\nif (app.Environment.IsDevelopment())\n{\n    app.UseSwagger();\n    app.UseSwaggerUI();\n}\n\napp.UseHttpsRedirection();\n\napp.UseCors(\"CorsPolicy\"); \/\/ CORS politikas\u0131n\u0131 etkinle\u015ftir\n\napp.UseAuthorization();\n\napp.MapControllers(); \/\/ E\u011fer API Controller kullan\u0131yorsan\u0131z\n\n\/\/ SignalR Hub'\u0131n\u0131 HTTP pipeline'\u0131na map et\napp.MapHub<NotificationHub>(\"\/notificationHub\"); \/\/ Angular'dan bu URL'ye ba\u011flanaca\u011f\u0131z\n\napp.Run();\n<\/pre>\n<p><\/code><\/p>\n<p>Bu yap\u0131land\u0131rma ile, <code>\/notificationHub<\/code> adresine yap\u0131lan istekler <code>NotificationHub<\/code> s\u0131n\u0131f\u0131n\u0131za y\u00f6nlendirilecektir. <strong>CORS ayarlar\u0131n\u0131n do\u011fru yap\u0131lmas\u0131 kritik \u00f6neme sahiptir<\/strong>, \u00e7\u00fcnk\u00fc Angular uygulaman\u0131z genellikle farkl\u0131 bir portta (\u00f6rn. 4200) \u00e7al\u0131\u015faca\u011f\u0131 i\u00e7in cross-origin iste\u011fi yapacakt\u0131r.<\/p>\n<h3>Ad\u0131m 5: Bir Controller'dan veya Servisten Mesaj G\u00f6nderme (Opsiyonel)<\/h3>\n<p>SignalR Hub'\u0131n\u0131za sadece istemcilerden de\u011fil, ayn\u0131 zamanda backend'inizdeki di\u011fer servislerden veya controller'lardan da mesaj g\u00f6nderebilirsiniz. Bu, bir API iste\u011fi i\u015flendikten sonra istemcilere bildirim g\u00f6ndermek istedi\u011finiz durumlarda kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<pre><code>\n\/\/ Controllers\/NotificationController.cs\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.SignalR;\nusing SignalRDemo.Api.Hubs;\nusing System.Threading.Tasks;\n\nnamespace SignalRDemo.Api.Controllers\n{\n    [ApiController]\n    [Route(\"[controller]\")]\n    public class NotificationController : ControllerBase\n    {\n        private readonly IHubContext<NotificationHub> _hubContext;\n\n        public NotificationController(IHubContext<NotificationHub> hubContext)\n        {\n            _hubContext = hubContext;\n        }\n\n        [HttpPost]\n        public async Task<IActionResult> PostNotification([FromBody] NotificationMessage message)\n        {\n            \/\/ T\u00fcm ba\u011fl\u0131 istemcilere notification g\u00f6nder\n            await _hubContext.Clients.All.SendAsync(\"ReceiveNotification\", message.User, message.Text);\n            return Ok();\n        }\n    }\n\n    public class NotificationMessage\n    {\n        public string User { get; set; }\n        public string Text { get; set; }\n    }\n}\n<\/pre>\n<p><\/code><\/p>\n<p>Bu \u00f6rnekte, <code>IHubContext<NotificationHub><\/code> interface'i inject edilerek, bir HTTP POST iste\u011fi geldi\u011finde SignalR Hub arac\u0131l\u0131\u011f\u0131yla t\u00fcm ba\u011fl\u0131 istemcilere bir bildirim g\u00f6nderilir. Art\u0131k .NET Core SignalR sunucunuz haz\u0131r! \u015eimdi Angular k\u0131sm\u0131na ge\u00e7ebiliriz.<\/p>\n<h2>Angular Uygulamas\u0131nda SignalR \u0130stemcisi Nas\u0131l Olu\u015fturulur?<\/h2>\n<p>.NET Core backend'imizi yap\u0131land\u0131rd\u0131\u011f\u0131m\u0131za g\u00f6re, \u015fimdi Angular uygulamas\u0131nda SignalR istemcisini nas\u0131l kuraca\u011f\u0131m\u0131z\u0131 ve backend'imizle nas\u0131l ileti\u015fim kuraca\u011f\u0131m\u0131z\u0131 g\u00f6relim. Bu b\u00f6l\u00fcm, Angular CLI ile proje olu\u015fturmaktan SignalR hizmetini yap\u0131land\u0131rmaya ve bile\u015fenlerinizde kullanmaya kadar uzanacak.<\/p>\n<h3>Ad\u0131m 1: Yeni Bir Angular Projesi Olu\u015fturma<\/h3>\n<p>E\u011fer hen\u00fcz bir Angular projeniz yoksa, Angular CLI kullanarak yeni bir proje olu\u015ftural\u0131m:<\/p>\n<pre><code>\nng new signalr-angular-client\ncd signalr-angular-client\n<\/pre>\n<p><\/code><\/p>\n<p>Bu komutlar, yeni bir Angular projesi olu\u015fturacak ve gerekli ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00fckleyecektir.<\/p>\n<h3>Ad\u0131m 2: SignalR \u0130stemci Paketini Kurma<\/h3>\n<p>Angular uygulaman\u0131zda SignalR ile etkile\u015fim kurabilmek i\u00e7in Microsoft'un SignalR JavaScript istemci k\u00fct\u00fcphanesini kurman\u0131z gerekir:<\/p>\n<pre><code>\nnpm install @microsoft\/signalr\n<\/pre>\n<p><\/code><\/p>\n<h3>Ad\u0131m 3: SignalR Ba\u011flant\u0131s\u0131n\u0131 Y\u00f6netecek Bir Hizmet Olu\u015fturma<\/h3>\n<p>SignalR ba\u011flant\u0131 mant\u0131\u011f\u0131n\u0131 ayr\u0131 bir hizmet i\u00e7inde tutmak, uygulaman\u0131z\u0131n daha temiz ve y\u00f6netilebilir olmas\u0131n\u0131 sa\u011flar. Angular CLI kullanarak bir hizmet olu\u015ftural\u0131m:<\/p>\n<pre><code>\nng generate service signalr\n<\/pre>\n<p><\/code><\/p>\n<p>\u015eimdi <code>src\/app\/signalr.service.ts<\/code> dosyas\u0131n\u0131 a\u015fa\u011f\u0131daki gibi d\u00fczenleyelim:<\/p>\n<pre><code>\n\/\/ src\/app\/signalr.service.ts\nimport { Injectable } from '@angular\/core';\nimport * as signalR from '@microsoft\/signalr';\nimport { Subject } from 'rxjs';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class SignalrService {\n  private hubConnection: signalR.HubConnection;\n  public data: Subject<any> = new Subject<any>(); \/\/ Sunucudan gelen verileri yaymak i\u00e7in\n  public connectionEstablished: Subject<boolean> = new Subject<boolean>();\n  private connectionIsEstablished = false;\n\n  constructor() { }\n\n  public startConnection = () => {\n    this.hubConnection = new signalR.HubConnectionBuilder()\n      .withUrl('https:\/\/localhost:7119\/notificationHub', { \/\/ .NET Core API'nizin adresi ve Hub yolu\n        skipNegotiation: true,\n        transport: signalR.HttpTransportType.WebSockets \/\/ WebSockets tercih et\n      })\n      .configureLogging(signalR.LogLevel.Information)\n      .build();\n\n    this.hubConnection\n      .start()\n      .then(() => {\n        console.log('SignalR ba\u011flant\u0131s\u0131 kuruldu.');\n        this.connectionIsEstablished = true;\n        this.connectionEstablished.next(true);\n      })\n      .catch(err => {\n        console.error('SignalR ba\u011flant\u0131s\u0131 kurulurken hata olu\u015ftu: ' + err);\n        this.connectionIsEstablished = false;\n        this.connectionEstablished.next(false);\n        \/\/ Hata durumunda yeniden deneme mekanizmas\u0131 eklenebilir\n        setTimeout(() => this.startConnection(), 5000);\n      });\n  }\n\n  public addTransferDataListener = () => {\n    this.hubConnection.on('ReceiveNotification', (user: string, message: string) => {\n      this.data.next({ user, message }); \/\/ Gelen veriyi Subject \u00fczerinden yay\u0131nla\n    });\n  }\n\n  public sendMessageToHub = (user: string, message: string) => {\n    if (this.hubConnection.state === signalR.HubConnectionState.Connected) {\n      this.hubConnection.invoke('SendNotification', user, message)\n        .catch(err => console.error('Hub\\'a mesaj g\u00f6nderilirken hata olu\u015ftu: ' + err));\n    } else {\n      console.warn('SignalR ba\u011flant\u0131s\u0131 mevcut de\u011fil. Mesaj g\u00f6nderilemedi.');\n    }\n  }\n\n  public stopConnection = () => {\n    if (this.hubConnection && this.hubConnection.state === signalR.HubConnectionState.Connected) {\n      this.hubConnection.stop()\n        .then(() => console.log('SignalR ba\u011flant\u0131s\u0131 kesildi.'))\n        .catch(err => console.error('SignalR ba\u011flant\u0131s\u0131 kesilirken hata olu\u015ftu: ' + err));\n    }\n  }\n}\n<\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki hizmet, SignalR ba\u011flant\u0131s\u0131n\u0131 y\u00f6netir. <code>startConnection<\/code> metodu sunucuya ba\u011flan\u0131r. <code>addTransferDataListener<\/code>, sunucudan gelecek 'ReceiveNotification' metodunu dinler ve gelen veriyi <code>data<\/code> Subject'i arac\u0131l\u0131\u011f\u0131yla di\u011fer bile\u015fenlere yayar. <code>sendMessageToHub<\/code> ise istemciden Hub'a mesaj g\u00f6ndermek i\u00e7in kullan\u0131l\u0131r.<\/p>\n<div class=\"expert-tip\">\n  <strong>Uzman \u0130pucu:<\/strong> <code>withUrl<\/code> metodu i\u00e7erisinde <code>skipNegotiation: true<\/code> ve <code>transport: signalR.HttpTransportType.WebSockets<\/code> kullanmak, SignalR'\u0131n do\u011frudan WebSockets ile ba\u011flant\u0131 kurmaya \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flar ve ba\u015flang\u0131\u00e7 ba\u011flant\u0131 s\u00fcresini k\u0131saltabilir. Ancak, eski taray\u0131c\u0131lar i\u00e7in fall-back mekanizmas\u0131n\u0131 devre d\u0131\u015f\u0131 b\u0131rak\u0131r.\n<\/div>\n<h3>Ad\u0131m 4: Bile\u015fenlerde SignalR Hizmetini Kullanma<\/h3>\n<p>\u015eimdi <code>SignalrService<\/code>'imizi bir Angular bile\u015feninde nas\u0131l kullanaca\u011f\u0131m\u0131z\u0131 g\u00f6relim. \u00d6rne\u011fin, <code>AppComponent<\/code> i\u00e7erisinde:<\/p>\n<pre><code>\n\/\/ src\/app\/app.component.ts\nimport { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { SignalrService } from '.\/signalr.service';\nimport { Subscription } from 'rxjs';\n\ninterface NotificationMessage {\n  user: string;\n  message: string;\n}\n\n@Component({\n  selector: 'app-root',\n  templateUrl: '.\/app.component.html',\n  styleUrls: ['.\/app.component.css']\n})\nexport class AppComponent implements OnInit, OnDestroy {\n  title = 'SignalR Real-Time Demo';\n  notifications: NotificationMessage[] = [];\n  newMessage: string = '';\n  userName: string = 'AngularClient';\n  private dataSubscription: Subscription;\n  private connectionSubscription: Subscription;\n\n  constructor(public signalrService: SignalrService) { }\n\n  ngOnInit() {\n    this.signalrService.startConnection();\n    this.connectionSubscription = this.signalrService.connectionEstablished.subscribe(connected => {\n      if (connected) {\n        this.signalrService.addTransferDataListener();\n        this.dataSubscription = this.signalrService.data.subscribe((message: NotificationMessage) => {\n          this.notifications.push(message);\n          console.log('Al\u0131nan bildirim:', message);\n        });\n      }\n    });\n  }\n\n  sendMessage() {\n    if (this.newMessage.trim()) {\n      this.signalrService.sendMessageToHub(this.userName, this.newMessage);\n      this.newMessage = ''; \/\/ Mesaj\u0131 g\u00f6nderdikten sonra giri\u015f alan\u0131n\u0131 temizle\n    }\n  }\n\n  ngOnDestroy() {\n    this.dataSubscription?.unsubscribe();\n    this.connectionSubscription?.unsubscribe();\n    this.signalrService.stopConnection(); \/\/ Ba\u011flant\u0131y\u0131 temizlemeyi unutmay\u0131n\n  }\n}\n<\/pre>\n<p><\/code><\/p>\n<p>Ve <code>src\/app\/app.component.html<\/code> dosyas\u0131n\u0131 da basit bir UI ile g\u00fcncelleyelim:<\/p>\n<pre><code>\n<div class=\"container\">\n  <h2>{{ title }}<\/h2>\n\n  <div class=\"input-group mb-3\">\n    <input type=\"text\" class=\"form-control\" placeholder=\"Kullan\u0131c\u0131 Ad\u0131\" [(ngModel)]=\"userName\">\n  <\/div>\n  <div class=\"input-group mb-3\">\n    <input type=\"text\" class=\"form-control\" placeholder=\"Mesaj\u0131n\u0131z\u0131 Yaz\u0131n...\" [(ngModel)]=\"newMessage\" (keyup.enter)=\"sendMessage()\">\n    <div class=\"input-group-append\">\n      <button class=\"btn btn-primary\" type=\"button\" (click)=\"sendMessage()\">G\u00f6nder<\/button>\n    <\/div>\n  <\/div>\n\n  <h3>Al\u0131nan Bildirimler:<\/h3>\n  <ul class=\"list-group\">\n    <li class=\"list-group-item\" *ngFor=\"let notif of notifications\">\n      <strong>{{ notif.user }}:<\/strong> {{ notif.message }}\n    <\/li>\n  <\/ul>\n<\/div>\n<\/pre>\n<p><\/code><\/p>\n<p>Bu \u00f6rnekte, <code>AppComponent<\/code>, <code>SignalrService<\/code>'i inject eder ve Angular uygulaman\u0131z ba\u015flad\u0131\u011f\u0131nda SignalR ba\u011flant\u0131s\u0131n\u0131 ba\u015flat\u0131r. Sunucudan gelen mesajlar <code>notifications<\/code> dizisine eklenir ve UI'da g\u00f6sterilir. Kullan\u0131c\u0131lar ayr\u0131ca kendi mesajlar\u0131n\u0131 da Hub'a g\u00f6nderebilirler. <code>OnDestroy<\/code> ya\u015fam d\u00f6ng\u00fcs\u00fc metodunda ba\u011flant\u0131y\u0131 ve abonelikleri temizlemek, haf\u0131za s\u0131z\u0131nt\u0131lar\u0131n\u0131 \u00f6nlemek i\u00e7in \u00f6nemlidir. Bu kurulumla, Angular istemciniz art\u0131k .NET Core SignalR sunucunuzla ger\u00e7ek zamanl\u0131 olarak ileti\u015fim kurmaya haz\u0131rd\u0131r!<\/p>\n<h2>Ger\u00e7ek D\u00fcnya Senaryosu: Anl\u0131k Borsa Takip Uygulamas\u0131<\/h2>\n<p>\u015eimdiye kadar SignalR'\u0131n temellerini ve .NET Core ile Angular'da nas\u0131l kurulaca\u011f\u0131n\u0131 \u00f6\u011frendik. Peki, bu bilgiyi ger\u00e7ek bir senaryoda nas\u0131l uygular\u0131z? Bir anl\u0131k borsa takip uygulamas\u0131, ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131n g\u00fcc\u00fcn\u00fc sergilemek i\u00e7in m\u00fckemmel bir \u00f6rnektir. Kullan\u0131c\u0131lar, hisse senedi fiyatlar\u0131ndaki anl\u0131k de\u011fi\u015fimleri gecikmesiz bir \u015fekilde g\u00f6rebilirler.<\/p>\n<h3>Senaryo: Borsa Verilerini Anl\u0131k G\u00fcncelleme<\/h3>\n<p>Hayal edelim ki bir hisse senedi takip uygulamas\u0131nda, sunucu taraf\u0131nda s\u00fcrekli olarak de\u011fi\u015fen hisse senedi fiyatlar\u0131 var ve bu fiyatlar\u0131n anl\u0131k olarak t\u00fcm ba\u011fl\u0131 istemcilere yans\u0131t\u0131lmas\u0131 gerekiyor. Bu senaryoda SignalR, sunucu ve istemciler aras\u0131ndaki k\u00f6pr\u00fc g\u00f6revi g\u00f6recektir. Backend'imiz sahte (mock) borsa verileri \u00fcretecek ve bunlar\u0131 d\u00fczenli aral\u0131klarla SignalR Hub'\u0131na g\u00f6nderecek, Angular frontend'imiz ise bu verileri al\u0131p UI'da g\u00f6sterecektir.<\/p>\n<h3>.NET Core Backend Taraf\u0131nda Uygulama<\/h3>\n<p>\u00d6ncelikle, hisse senedi fiyatlar\u0131n\u0131 sim\u00fcle eden ve bunlar\u0131 SignalR Hub'\u0131na yay\u0131nlayan bir servis olu\u015ftural\u0131m. Bunun i\u00e7in <code>StockTickerHub.cs<\/code> ad\u0131nda yeni bir Hub ve bir de arka plan servisi (<code>BackgroundService<\/code>) tan\u0131mlayaca\u011f\u0131z.<\/p>\n<pre><code>\n\/\/ Hubs\/StockTickerHub.cs\nusing Microsoft.AspNetCore.SignalR;\nusing System.Threading.Tasks;\n\nnamespace SignalRDemo.Api.Hubs\n{\n    public class StockTickerHub : Hub\n    {\n        \/\/ \u0130stemciler bu Hub'a ba\u011flanabilir ve metodlar\u0131 \u00e7a\u011f\u0131rabilir.\n        \/\/ Bu \u00f6rnekte, sunucudan istemciye push odakl\u0131y\u0131z.\n        \/\/ Ancak istemcilerin de sunucuya \u00f6zel istekler g\u00f6ndermesi i\u00e7in metodlar eklenebilir.\n        public async Task JoinStockGroup(string stockSymbol)\n        {\n            await Groups.AddToGroupAsync(Context.ConnectionId, stockSymbol);\n            await Clients.Caller.SendAsync(\"ReceiveNotification\", \"Server\", $\"{stockSymbol} grubuna kat\u0131ld\u0131n\u0131z.\");\n        }\n\n        public async Task LeaveStockGroup(string stockSymbol)\n        {\n            await Groups.RemoveFromGroupAsync(Context.ConnectionId, stockSymbol);\n            await Clients.Caller.SendAsync(\"ReceiveNotification\", \"Server\", $\"{stockSymbol} grubundan ayr\u0131ld\u0131n\u0131z.\");\n        }\n    }\n\n    public class StockPrice\n    {\n        public string Symbol { get; set; }\n        public decimal Price { get; set; }\n        public DateTime LastUpdated { get; set; }\n    }\n}\n<\/pre>\n<p><\/code><\/p>\n<p>\u015eimdi bu Hub'a d\u00fczenli olarak veri g\u00f6nderecek bir arka plan servisi olu\u015ftural\u0131m:<\/p>\n<pre><code>\n\/\/ Services\/StockSimulatorService.cs\nusing Microsoft.AspNetCore.SignalR;\nusing SignalRDemo.Api.Hubs;\nusing System.Collections.Concurrent;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System;\nusing Microsoft.Extensions.Hosting;\n\nnamespace SignalRDemo.Api.Services\n{\n    public class StockSimulatorService : BackgroundService\n    {\n        private readonly IHubContext<StockTickerHub> _hubContext;\n        private readonly ConcurrentDictionary<string, StockPrice> _stockPrices;\n        private readonly Random _random;\n\n        public StockSimulatorService(IHubContext<StockTickerHub> hubContext)\n        {\n            _hubContext = hubContext;\n            _stockPrices = new ConcurrentDictionary<string, StockPrice>();\n            _random = new Random();\n\n            \/\/ Ba\u015flang\u0131\u00e7 hisse senetleri\n            _stockPrices.TryAdd(\"MSFT\", new StockPrice { Symbol = \"MSFT\", Price = 250.00m, LastUpdated = DateTime.UtcNow });\n            _stockPrices.TryAdd(\"GOOG\", new StockPrice { Symbol = \"GOOG\", Price = 1500.00m, LastUpdated = DateTime.UtcNow });\n            _stockPrices.TryAdd(\"AAPL\", new StockPrice { Symbol = \"AAPL\", Price = 170.00m, LastUpdated = DateTime.UtcNow });\n        }\n\n        protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n        {\n            while (!stoppingToken.IsCancellationRequested)\n            {\n                await Task.Delay(2000, stoppingToken); \/\/ Her 2 saniyede bir g\u00fcncelle\n\n                foreach (var symbol in _stockPrices.Keys)\n                {\n                    \/\/ Fiyatlar\u0131 rastgele g\u00fcncelle\n                    _stockPrices.TryGetValue(symbol, out var currentPrice);\n                    if (currentPrice != null)\n                    {\n                        var change = (decimal)(_random.NextDouble() * 10 - 5); \/\/ -5 ile +5 aras\u0131nda de\u011fi\u015fim\n                        currentPrice.Price += change;\n                        currentPrice.LastUpdated = DateTime.UtcNow;\n\n                        \/\/ T\u00fcm ba\u011fl\u0131 istemcilere g\u00fcncellenmi\u015f fiyat\u0131 g\u00f6nder\n                        await _hubContext.Clients.All.SendAsync(\"ReceiveStockUpdate\", currentPrice);\n\n                        \/\/ Veya sadece ilgili gruba g\u00f6ndermek i\u00e7in:\n                        \/\/ await _hubContext.Clients.Group(symbol).SendAsync(\"ReceiveStockUpdate\", currentPrice);\n                    }\n                }\n            }\n        }\n    }\n}\n<\/pre>\n<p><\/code><\/p>\n<p><code>Program.cs<\/code> dosyan\u0131za hem <code>StockTickerHub<\/code>'\u0131 map etmeyi hem de <code>StockSimulatorService<\/code>'i eklemeyi unutmay\u0131n:<\/p>\n<pre><code>\n\/\/ Program.cs\n\/\/ ... (\u00f6nceki kodlar)\nusing SignalRDemo.Api.Services;\n\n\/\/ SignalR servislerini ekle\nbuilder.Services.AddSignalR();\nbuilder.Services.AddHostedService<StockSimulatorService>(); \/\/ Arka plan servisini ekle\n\/\/ ... (di\u011fer servisler)\n\nvar app = builder.Build();\n\n\/\/ ... (orta katmanlar)\n\napp.MapHub<NotificationHub>(\"\/notificationHub\");\napp.MapHub<StockTickerHub>(\"\/stockTickerHub\"); \/\/ Yeni StockTickerHub'\u0131 map et\n\napp.Run();\n<\/pre>\n<p><\/code><\/p>\n<h3>Angular Frontend Taraf\u0131nda Uygulama<\/h3>\n<p>Angular taraf\u0131nda, yeni bir hizmet (<code>StockTickerService<\/code>) olu\u015fturarak <code>StockTickerHub<\/code>'a ba\u011flanaca\u011f\u0131z ve gelen hisse senedi g\u00fcncellemelerini i\u015fleyece\u011fiz.<\/p>\n<pre><code>\n\/\/ src\/app\/stock-ticker.service.ts\nimport { Injectable } from '@angular\/core';\nimport * as signalR from '@microsoft\/signalr';\nimport { Subject } from 'rxjs';\n\nexport interface StockPrice {\n  symbol: string;\n  price: number;\n  lastUpdated: string;\n}\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class StockTickerService {\n  private hubConnection: signalR.HubConnection;\n  public stockUpdates: Subject<StockPrice> = new Subject<StockPrice>();\n  public connectionStatus: Subject<boolean> = new Subject<boolean>();\n\n  constructor() { }\n\n  public startConnection = () => {\n    this.hubConnection = new signalR.HubConnectionBuilder()\n      .withUrl('https:\/\/localhost:7119\/stockTickerHub', {\n        skipNegotiation: true,\n        transport: signalR.HttpTransportType.WebSockets\n      })\n      .configureLogging(signalR.LogLevel.Information)\n      .build();\n\n    this.hubConnection\n      .start()\n      .then(() => {\n        console.log('Stock Ticker SignalR ba\u011flant\u0131s\u0131 kuruldu.');\n        this.connectionStatus.next(true);\n        this.addStockUpdateListener();\n      })\n      .catch(err => {\n        console.error('Stock Ticker SignalR ba\u011flant\u0131s\u0131 kurulurken hata olu\u015ftu: ' + err);\n        this.connectionStatus.next(false);\n        setTimeout(() => this.startConnection(), 5000); \/\/ Ba\u011flant\u0131 hatas\u0131nda yeniden dene\n      });\n  }\n\n  private addStockUpdateListener = () => {\n    this.hubConnection.on('ReceiveStockUpdate', (stock: StockPrice) => {\n      this.stockUpdates.next(stock);\n    });\n  }\n\n  public stopConnection = () => {\n    if (this.hubConnection && this.hubConnection.state === signalR.HubConnectionState.Connected) {\n      this.hubConnection.stop()\n        .then(() => console.log('Stock Ticker SignalR ba\u011flant\u0131s\u0131 kesildi.'))\n        .catch(err => console.error('Stock Ticker SignalR ba\u011flant\u0131s\u0131 kesilirken hata olu\u015ftu: ' + err));\n    }\n  }\n\n  public joinStockGroup(symbol: string) {\n    if (this.hubConnection.state === signalR.HubConnectionState.Connected) {\n      this.hubConnection.invoke('JoinStockGroup', symbol)\n        .catch(err => console.error('Hisse senedi grubuna kat\u0131l\u0131rken hata olu\u015ftu: ' + err));\n    }\n  }\n\n  public leaveStockGroup(symbol: string) {\n    if (this.hubConnection.state === signalR.HubConnectionState.Connected) {\n      this.hubConnection.invoke('LeaveStockGroup', symbol)\n        .catch(err => console.error('Hisse senedi grubundan ayr\u0131l\u0131rken hata olu\u015ftu: ' + err));\n    }\n  }\n}\n<\/pre>\n<p><\/code><\/p>\n<p>\u015eimdi bu hizmeti bir Angular bile\u015feninde (\u00f6rn. <code>StockTickerComponent<\/code>) kullanal\u0131m:<\/p>\n<pre><code>\n\/\/ src\/app\/stock-ticker\/stock-ticker.component.ts\nimport { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { StockTickerService, StockPrice } from '..\/stock-ticker.service';\nimport { Subscription } from 'rxjs';\n\n@Component({\n  selector: 'app-stock-ticker',\n  templateUrl: '.\/stock-ticker.component.html',\n  styleUrls: ['.\/stock-ticker.component.css']\n})\nexport class StockTickerComponent implements OnInit, OnDestroy {\n  currentStockPrices: { [key: string]: StockPrice } = {};\n  private stockUpdateSubscription: Subscription;\n  private connectionStatusSubscription: Subscription;\n  isConnected: boolean = false;\n\n  constructor(private stockTickerService: StockTickerService) { }\n\n  ngOnInit(): void {\n    this.stockTickerService.startConnection();\n    this.connectionStatusSubscription = this.stockTickerService.connectionStatus.subscribe(status => {\n      this.isConnected = status;\n      if (status) {\n        this.stockUpdateSubscription = this.stockTickerService.stockUpdates.subscribe(stock => {\n          this.currentStockPrices[stock.symbol] = stock;\n        });\n      } else {\n        this.stockUpdateSubscription?.unsubscribe();\n      }\n    });\n  }\n\n  ngOnDestroy(): void {\n    this.stockUpdateSubscription?.unsubscribe();\n    this.connectionStatusSubscription?.unsubscribe();\n    this.stockTickerService.stopConnection();\n  }\n\n  \/\/ \u0130stemcinin belirli hisse senetlerine abone olmas\u0131n\u0131 sa\u011flayan metodlar\n  joinStockGroup(symbol: string) {\n    this.stockTickerService.joinStockGroup(symbol);\n  }\n\n  leaveStockGroup(symbol: string) {\n    this.stockTickerService.leaveStockGroup(symbol);\n  }\n}\n<\/pre>\n<p><\/code><\/p>\n<p>Ve basit bir UI i\u00e7in <code>stock-ticker.component.html<\/code>:<\/p>\n<pre><code>\n<div class=\"stock-ticker-container\">\n  <h2>Anl\u0131k Borsa Takip<\/h2>\n  <p>Ba\u011flant\u0131 Durumu: <strong [class.text-success]=\"isConnected\" [class.text-danger]=\"!isConnected\">{{ isConnected ? 'Ba\u011fl\u0131' : 'Ba\u011flant\u0131 Yok' }}<\/strong><\/p>\n\n  <table class=\"stock-table\">\n    <thead>\n      <tr>\n        <th>Sembol<\/th>\n        <th>Fiyat<\/th>\n        <th>Son G\u00fcncelleme<\/th>\n        <th>\u0130\u015flem<\/th>\n      <\/tr>\n    <\/thead>\n    <tbody>\n      <tr *ngFor=\"let stockSymbol of (currentStockPrices | keyvalue)\">\n        <td>{{ stockSymbol.value.symbol }}<\/td>\n        <td [class.price-up]=\"stockSymbol.value.price > (currentStockPrices[stockSymbol.key]?.price || 0)\" [class.price-down]=\"stockSymbol.value.price < (currentStockPrices[stockSymbol.key]?.price || 0)\">\n          {{ stockSymbol.value.price | currency:'USD':'symbol':'1.2-2' }}\n        <\/td>\n        <td>{{ stockSymbol.value.lastUpdated | date:'mediumTime' }}<\/td>\n        <td>\n          <button class=\"btn btn-sm btn-info\" (click)=\"joinStockGroup(stockSymbol.value.symbol)\">Gruba Kat\u0131l<\/button>\n          <button class=\"btn btn-sm btn-warning\" (click)=\"leaveStockGroup(stockSymbol.value.symbol)\">Gruptan Ayr\u0131l<\/button>\n        <\/td>\n      <\/tr>\n    <\/tbody>\n  <\/table>\n<\/div>\n\n<style>\n  .stock-ticker-container {\n    max-width: 800px;\n    margin: 20px auto;\n    padding: 20px;\n    border: 1px solid #ddd;\n    border-radius: 8px;\n    background-color: #f9f9f9;\n  }\n  .stock-table {\n    width: 100%;\n    border-collapse: collapse;\n    margin-top: 15px;\n  }\n  .stock-table th, .stock-table td {\n    border: 1px solid #eee;\n    padding: 8px;\n    text-align: left;\n  }\n  .stock-table th {\n    background-color: #eef;\n    font-weight: bold;\n  }\n  .price-up {\n    color: green;\n    font-weight: bold;\n  }\n  .price-down {\n    color: red;\n    font-weight: bold;\n  }\n  .btn {\n    padding: 5px 10px;\n    margin-right: 5px;\n    border: none;\n    border-radius: 4px;\n    cursor: pointer;\n  }\n  .btn-info {\n    background-color: #17a2b8;\n    color: white;\n  }\n  .btn-warning {\n    background-color: #ffc107;\n    color: black;\n  }\n\n  \/* Mobil Uyumlu Tasar\u0131m *\/\n  @media (max-width: 768px) {\n    .stock-ticker-container {\n      margin: 10px;\n      padding: 10px;\n    }\n    .stock-table, .stock-table tbody, .stock-table tr, .stock-table td {\n      display: block;\n      width: 100%;\n    }\n    .stock-table thead {\n      display: none; \/* Ba\u015fl\u0131klar\u0131 mobil g\u00f6r\u00fcn\u00fcmde gizle *\/\n    }\n    .stock-table td {\n      border: none;\n      border-bottom: 1px solid #eee;\n      position: relative;\n      padding-left: 50%; \/* Etiket i\u00e7in yer a\u00e7 *\/\n      text-align: right;\n    }\n    .stock-table td::before {\n      content: attr(data-label); \/* data-label niteli\u011fini etiket olarak kullan *\/\n      position: absolute;\n      left: 6px;\n      width: 45%;\n      padding-right: 10px;\n      white-space: nowrap;\n      text-align: left;\n      font-weight: bold;\n    }\n    \/* Her bir td'ye data-label eklemeyi unutmay\u0131n *\/\n    .stock-table tr td:nth-of-type(1)::before { content: \"Sembol:\"; }\n    .stock-table tr td:nth-of-type(2)::before { content: \"Fiyat:\"; }\n    .stock-table tr td:nth-of-type(3)::before { content: \"G\u00fcncelleme:\"; }\n    .stock-table tr td:nth-of-type(4)::before { content: \"\u0130\u015flem:\"; }\n  }\n<\/style>\n<\/pre>\n<p><\/code><\/p>\n<p>Bu senaryo, SignalR'\u0131n sadece mesajla\u015fma i\u00e7in de\u011fil, ayn\u0131 zamanda s\u00fcrekli g\u00fcncellenen ve kritik verilerin an\u0131nda iletilmesi gereken durumlar i\u00e7in de ne kadar g\u00fc\u00e7l\u00fc oldu\u011funu g\u00f6stermektedir. Kullan\u0131c\u0131lar art\u0131k hisse senedi fiyatlar\u0131n\u0131 an\u0131nda takip edebilir ve uygulamadan ayr\u0131lmadan en g\u00fcncel bilgilere eri\u015febilirler.<\/p>\n<h2>Performans ve \u00d6l\u00e7eklenebilirlik \u0130\u00e7in \u0130pu\u00e7lar\u0131<\/h2>\n<p>Ger\u00e7ek zamanl\u0131 uygulamalar geli\u015ftirirken performans ve \u00f6l\u00e7eklenebilirlik her zaman \u00f6n planda olmal\u0131d\u0131r. \u0130\u015fte SignalR uygulamalar\u0131n\u0131z\u0131 daha performansl\u0131 ve \u00f6l\u00e7eklenebilir hale getirmek i\u00e7in baz\u0131 \u00f6nemli ipu\u00e7lar\u0131:<\/p>\n<h3>1. Azure SignalR Service Kullan\u0131m\u0131<\/h3>\n<p>Azure SignalR Service, \u00f6zellikle y\u00fcksek trafikli veya birden fazla sunucuya yay\u0131lm\u0131\u015f uygulamalar i\u00e7in vazge\u00e7ilmez bir \u00e7\u00f6z\u00fcmd\u00fcr. Geleneksel olarak, SignalR'\u0131 kendi sunucular\u0131n\u0131zda bar\u0131nd\u0131rd\u0131\u011f\u0131n\u0131zda, birden fazla sunucu aras\u0131nda istemci ba\u011flant\u0131lar\u0131n\u0131 ve mesajlar\u0131n\u0131 y\u00f6netmek i\u00e7in bir \"backplane\" (\u00f6rn. Redis) kullanman\u0131z gerekir. Azure SignalR Service, bu backplane y\u00f6netimini sizin i\u00e7in \u00fcstlenir, sunucu kaynaklar\u0131n\u0131z\u0131 bo\u015falt\u0131r ve uygulaman\u0131z\u0131n \u00f6l\u00e7eklenmesini \u00e7ok daha kolay hale getirir. Sunucular\u0131n\u0131z sadece i\u015f mant\u0131\u011f\u0131n\u0131za odaklan\u0131rken, ba\u011flant\u0131 y\u00f6netimi, mesajla\u015fma ve \u00f6l\u00e7eklendirme Azure taraf\u0131ndan y\u00f6netilir.<\/p>\n<pre><code>\n\/\/ Azure SignalR Service entegrasyonu i\u00e7in Program.cs'de yap\u0131lan de\u011fi\u015fiklikler\n\/\/ builder.Services.AddSignalR().AddAzureSignalR(); \/\/ Bu sat\u0131r\u0131 kullan\u0131n\nbuilder.Services.AddSignalR()\n    .AddAzureSignalR(options =>\n    {\n        options.ConnectionString = builder.Configuration[\"Azure:SignalR:ConnectionString\"];\n        \/\/ Ayr\u0131ca service mode'u veya di\u011fer ayarlar\u0131 da yap\u0131land\u0131rabilirsiniz\n    });\n<\/pre>\n<p><\/code><\/p>\n<h3>2. Mesaj Boyutunu ve S\u0131kl\u0131\u011f\u0131n\u0131 Optimize Etme<\/h3>\n<p>G\u00f6nderdi\u011finiz mesajlar\u0131n boyutu ve g\u00f6nderilme s\u0131kl\u0131\u011f\u0131 performans\u0131 do\u011frudan etkiler. B\u00fcy\u00fck veya \u00e7ok s\u0131k g\u00f6nderilen mesajlar a\u011f trafi\u011fini art\u0131r\u0131r, istemci ve sunucu kaynaklar\u0131n\u0131 t\u00fcketir. Gereksiz verileri filtreleyerek sadece ihtiyac\u0131n\u0131z olan\u0131 g\u00f6nderin. \u00d6rne\u011fin, bir hisse senedi g\u00fcncellemesinde sadece de\u011fi\u015fen alanlar\u0131 g\u00f6nderebilirsiniz. Ayr\u0131ca, h\u0131zl\u0131 de\u011fi\u015fen veriler i\u00e7in her de\u011fi\u015fiklikte mesaj g\u00f6ndermek yerine, belirli bir zaman aral\u0131\u011f\u0131nda (\u00f6rn. her 200 ms) en son durumu toplu olarak g\u00f6ndermeyi d\u00fc\u015f\u00fcnebilirsiniz (throttle\/debounce).<\/p>\n<h3>3. Grup Y\u00f6netimi ve Hedefli Mesajla\u015fma<\/h3>\n<p><code>Clients.All.SendAsync()<\/code> metodunu kullanmak t\u00fcm ba\u011fl\u0131 istemcilere mesaj g\u00f6nderir ve bu, b\u00fcy\u00fck \u00f6l\u00e7ekli uygulamalarda performans sorunlar\u0131na yol a\u00e7abilir. Bunun yerine, istemcileri mant\u0131ksal gruplara ay\u0131rarak sadece ilgili gruplara mesaj g\u00f6ndermeyi tercih edin. \u00d6rne\u011fin, bir sohbet uygulamas\u0131nda kullan\u0131c\u0131lar\u0131 sohbet odalar\u0131na g\u00f6re gruplayabilir, bir borsa uygulamas\u0131nda ise belirli hisse senetlerini takip eden kullan\u0131c\u0131lar\u0131 ayr\u0131 gruplara alabilirsiniz. Bu, gereksiz mesaj trafi\u011fini azalt\u0131r ve sunucu y\u00fck\u00fcn\u00fc hafifletir.<\/p>\n<pre><code>\n\/\/ Belirli bir gruba mesaj g\u00f6nderme\nawait _hubContext.Clients.Group(\"MSFT_StockUsers\").SendAsync(\"ReceiveStockUpdate\", stockPrice);\n\n\/\/ \u0130stemcinin bir gruba kat\u0131lmas\u0131\npublic async Task JoinGroup(string groupName)\n{\n    await Groups.AddToGroupAsync(Context.ConnectionId, groupName);\n    await Clients.Caller.SendAsync(\"Message\", $\"'{groupName}' grubuna kat\u0131ld\u0131n\u0131z.\");\n}\n<\/pre>\n<p><\/code><\/p>\n<h3>4. Yetkilendirme ve Kimlik Do\u011frulama<\/h3>\n<p>SignalR ba\u011flant\u0131lar\u0131n\u0131z\u0131n g\u00fcvenli\u011fini sa\u011flamak i\u00e7in yetkilendirme ve kimlik do\u011frulama mekanizmalar\u0131n\u0131 kullan\u0131n. .NET Core'un Identity ve JWT (JSON Web Token) entegrasyonlar\u0131 ile SignalR Hub'lar\u0131n\u0131za eri\u015fimi k\u0131s\u0131tlayabilirsiniz. Sadece yetkili kullan\u0131c\u0131lar\u0131n belirli Hub'lara veya metodlara eri\u015fmesine izin vermek, hem g\u00fcvenli\u011fi art\u0131r\u0131r hem de gereksiz ba\u011flant\u0131lar\u0131 ve kaynak t\u00fcketimini \u00f6nler.<\/p>\n<pre><code>\n\/\/ Hub \u00fczerinde yetkilendirme attribute'u kullanma\n[Authorize] \/\/ Bu Hub'a eri\u015fim i\u00e7in yetkilendirme gereklidir\npublic class SecuredChatHub : Hub\n{\n    \/\/ ...\n}\n\n\/\/ \u0130stemci taraf\u0131nda JWT ile ba\u011flant\u0131 kurma (Angular \u00f6rne\u011fi)\nconst connection = new signalR.HubConnectionBuilder()\n    .withUrl('https:\/\/localhost:7119\/securedHub', {\n        accessTokenFactory: () => {\n            \/\/ JWT token'\u0131n\u0131z\u0131 buradan d\u00f6nd\u00fcr\u00fcn\n            return localStorage.getItem('jwtToken');\n        }\n    })\n    .build();\n<\/pre>\n<p><\/code><\/p>\n<h3>5. Hata Y\u00f6netimi ve Yeniden Ba\u011flant\u0131 Stratejileri<\/h3>\n<p>A\u011f kesintileri veya sunucu problemleri nedeniyle SignalR ba\u011flant\u0131lar\u0131 kesilebilir. Hem sunucu hem de istemci taraf\u0131nda sa\u011flam hata y\u00f6netimi ve otomatik yeniden ba\u011flant\u0131 stratejileri uygulamak \u00f6nemlidir. SignalR istemcisi, varsay\u0131lan olarak yeniden ba\u011flant\u0131 dener, ancak bu davran\u0131\u015f\u0131 \u00f6zelle\u015ftirebilirsiniz. Sunucu taraf\u0131nda ise ba\u011flant\u0131 kesintilerini loglayarak sorunlar\u0131 tespit edebilirsiniz.<\/p>\n<pre><code>\n\/\/ \u0130stemci taraf\u0131nda \u00f6zel yeniden ba\u011flant\u0131 stratejisi (Angular)\nthis.hubConnection = new signalR.HubConnectionBuilder()\n    .withUrl('https:\/\/localhost:7119\/notificationHub')\n    .withAutomaticReconnect({\n      nextRetryDelayInMilliseconds: retryContext => {\n        if (retryContext.elapsedMilliseconds < 60000) {\n          \/\/ \u0130lk dakika i\u00e7inde 0, 2, 10, 30 saniye sonra tekrar dene\n          return [0, 2000, 10000, 30000][retryContext.previousRetryCount];\n        }\n        \/\/ Bir dakikadan sonra her zaman 30 saniye sonra tekrar dene\n        return 30000;\n      }\n    })\n    .build();\n<\/pre>\n<p><\/code><\/p>\n<p>Bu ipu\u00e7lar\u0131, SignalR uygulamalar\u0131n\u0131z\u0131n daha sa\u011flam, g\u00fcvenli ve performansl\u0131 olmas\u0131n\u0131 sa\u011flayarak ger\u00e7ek d\u00fcnya senaryolar\u0131na haz\u0131r hale gelmesine yard\u0131mc\u0131 olacakt\u0131r.<\/p>\n<h2>Sonu\u00e7 ve Gelecek Perspektifi<\/h2>\n<p>Bu makale boyunca, .NET Core ve Angular uygulamalar\u0131n\u0131zda ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131 sa\u011flamak i\u00e7in SignalR'\u0131n nas\u0131l kullan\u0131laca\u011f\u0131n\u0131 detayl\u0131 bir \u015fekilde inceledik. Geleneksel istek-yan\u0131t modelinin s\u0131n\u0131rl\u0131l\u0131klar\u0131ndan, SignalR'\u0131n temel bile\u015fenlerine, ad\u0131m ad\u0131m kurulumundan, ger\u00e7ek d\u00fcnya borsa takip senaryosuna ve nihayet performans ile \u00f6l\u00e7eklenebilirlik ipu\u00e7lar\u0131na kadar geni\u015f bir yelpazede bilgi edindik. G\u00f6rd\u00fc\u011f\u00fcm\u00fcz gibi, SignalR, geli\u015ftiricilere WebSockets ve di\u011fer transport mekanizmalar\u0131n\u0131 soyutlayarak, sunucudan istemciye anl\u0131k veri push etme yetene\u011fi sunar.<\/p>\n<p>Bug\u00fcn\u00fcn modern web uygulamalar\u0131nda anl\u0131k bildirimler, canl\u0131 sohbetler, dinamik dashboard'lar ve \u00e7ok kullan\u0131c\u0131l\u0131 etkile\u015fimler vazge\u00e7ilmez hale gelmi\u015ftir. SignalR, .NET Core'un g\u00fcc\u00fc ve Angular'\u0131n esnekli\u011fi ile birle\u015fti\u011finde, bu beklentileri kar\u015f\u0131lamak i\u00e7in sa\u011flam, h\u0131zl\u0131 ve \u00f6l\u00e7eklenebilir bir temel olu\u015fturur. Azure SignalR Service gibi bulut \u00e7\u00f6z\u00fcmleriyle entegre edildi\u011finde ise, uygulaman\u0131z\u0131n milyonlarca kullan\u0131c\u0131ya hizmet verebilecek kapasiteye ula\u015fmas\u0131 olduk\u00e7a kolayla\u015f\u0131r.<\/p>\n<p>Gelecekte, ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131n \u00f6nemi daha da artacak. Nesnelerin \u0130nterneti (IoT), yapay zeka destekli ak\u0131ll\u0131 sistemler ve giderek daha fazla interaktif hale gelen kullan\u0131c\u0131 aray\u00fczleri, anl\u0131k ve d\u00fc\u015f\u00fck gecikmeli ileti\u015fimi daha da kritik hale getirecek. SignalR gibi teknolojiler, bu yeni nesil uygulamalar\u0131n geli\u015ftirilmesinde kilit bir rol oynamaya devam edecektir. Bu makaledeki bilgilerle donanarak, kendi ger\u00e7ek zamanl\u0131 uygulamalar\u0131n\u0131z\u0131 ba\u015far\u0131yla in\u015fa edebilir ve kullan\u0131c\u0131lar\u0131n\u0131za ola\u011fan\u00fcst\u00fc deneyimler sunabilirsiniz.<\/p>\n<h2>S\u0131k\u00e7a Sorulan Sorular (SSS)<\/h2>\n<h3>1. SignalR yerine do\u011frudan WebSockets kullanmak daha m\u0131 iyi?<\/h3>\n<p>SignalR, WebSockets, Server-Sent Events ve Long Polling gibi alt d\u00fczey transport mekanizmalar\u0131n\u0131 soyutlayan bir k\u00fct\u00fcphanedir. Do\u011frudan WebSockets kullanmak, tam kontrol sa\u011flasa da, ba\u011flant\u0131 y\u00f6netimi, yeniden ba\u011flant\u0131, gruplama ve hata y\u00f6netimi gibi karma\u015f\u0131k durumlar\u0131 manuel olarak halletmenizi gerektirir. SignalR bu zorluklar\u0131 sizin i\u00e7in y\u00f6netir, b\u00f6ylece geli\u015ftiriciler daha \u00e7ok i\u015f mant\u0131\u011f\u0131na odaklanabilir. \u00c7o\u011fu senaryo i\u00e7in SignalR, hem kolayl\u0131k hem de performans a\u00e7\u0131s\u0131ndan daha iyi bir tercihtir. Sadece \u00e7ok \u00f6zel performans veya kontrol gereksinimleriniz varsa do\u011frudan WebSockets d\u00fc\u015f\u00fcnebilirsiniz.<\/p>\n<h3>2. SignalR g\u00fcvenlik konusunda neler sunuyor?<\/h3>\n<p>SignalR, ASP.NET Core g\u00fcvenlik \u00f6zellikleriyle tam entegredir. Kimlik do\u011frulama (Authentication) ve yetkilendirme (Authorization) mekanizmalar\u0131n\u0131 kullanarak Hub'lar\u0131n\u0131za ve Hub metodlar\u0131n\u0131za eri\u015fimi k\u0131s\u0131tlayabilirsiniz. \u00d6rne\u011fin, JWT token'lar\u0131 ile kullan\u0131c\u0131lar\u0131 do\u011frulayabilir ve <code>[Authorize]<\/code> attribute'u ile sadece belirli rollere sahip kullan\u0131c\u0131lar\u0131n belirli metodlar\u0131 \u00e7a\u011f\u0131rmas\u0131na izin verebilirsiniz. Ayr\u0131ca, HTTPS \u00fczerinden ba\u011flant\u0131 kurarak ileti\u015fim kanal\u0131n\u0131n g\u00fcvenli\u011fini sa\u011flamak her zaman \u00f6nerilir.<\/p>\n<h3>3. SignalR'\u0131 hangi durumlarda kullanmal\u0131y\u0131m?<\/h3>\n<p>SignalR, sunucudan istemcilere an\u0131nda veri iletimi gereken her t\u00fcrl\u00fc senaryo i\u00e7in idealdir. Ba\u015fl\u0131ca kullan\u0131m durumlar\u0131 \u015funlard\u0131r:<\/p>\n<ul>\n<li>Canl\u0131 sohbet uygulamalar\u0131<\/li>\n<li>Anl\u0131k bildirim sistemleri<\/li>\n<li>Borsa takip, spor skorlar\u0131 gibi canl\u0131 veri ak\u0131\u015flar\u0131<\/li>\n<li>\u00c7ok kullan\u0131c\u0131l\u0131 \u00e7evrimi\u00e7i oyunlar<\/li>\n<li>Ger\u00e7ek zamanl\u0131 g\u00f6sterge panolar\u0131 (dashboard'lar) ve izleme sistemleri<\/li>\n<li>Co\u011frafi konum takibi<\/li>\n<li>Anket ve oylama sistemleri<\/li>\n<\/ul>\n<h3>4. SignalR'\u0131n \u00f6l\u00e7eklenebilirlik limitleri nelerdir?<\/h3>\n<p>Tek ba\u015f\u0131na bir SignalR sunucusu, binlerce e\u015fzamanl\u0131 ba\u011flant\u0131y\u0131 y\u00f6netebilir. Ancak, uygulaman\u0131z daha fazla trafik ve ba\u011flant\u0131 gerektirdi\u011finde, \u00f6l\u00e7eklenebilirlik bir endi\u015fe haline gelebilir. Birden fazla sunucuya yay\u0131lm\u0131\u015f bir SignalR kurulumunda, sunucular aras\u0131 ileti\u015fimi sa\u011flamak i\u00e7in bir \"backplane\" (\u00f6rn. Redis veya SQL Server tabanl\u0131 bir backplane) kullanman\u0131z gerekir. En iyi ve en kolay \u00f6l\u00e7eklenebilirlik \u00e7\u00f6z\u00fcm\u00fc ise Azure SignalR Service kullanmakt\u0131r. Azure SignalR Service, backplane y\u00f6netimini, ba\u011flant\u0131 y\u00fck dengelemesini ve y\u00fcksek kullan\u0131labilirli\u011fi otomatik olarak sa\u011flayarak uygulaman\u0131z\u0131n milyonlarca e\u015fzamanl\u0131 kullan\u0131c\u0131ya ula\u015fmas\u0131n\u0131 destekler.<\/p>\n<h3>5. Angular d\u0131\u015f\u0131nda ba\u015fka framework'lerle SignalR kullan\u0131labilir mi?<\/h3>\n<p>Evet, kesinlikle! SignalR'\u0131n \u00e7e\u015fitli platformlar i\u00e7in istemci k\u00fct\u00fcphaneleri bulunmaktad\u0131r. JavaScript istemci k\u00fct\u00fcphanesi, Angular'\u0131n yan\u0131 s\u0131ra React, Vue.js veya Vanilla JavaScript ile de kullan\u0131labilir. Ayr\u0131ca, .NET (WPF, WinForms, Blazor), Java, Python ve daha bir\u00e7ok platform i\u00e7in istemci k\u00fct\u00fcphaneleri veya topluluk taraf\u0131ndan geli\u015ftirilmi\u015f adapt\u00f6rler mevcuttur. Bu sayede, .NET Core SignalR backend'inizi kullanarak farkl\u0131 teknolojilerdeki bir\u00e7ok frontend veya istemci uygulamas\u0131na ger\u00e7ek zamanl\u0131 yetenekler ekleyebilirsiniz.<\/p>\n<p><\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1340],"tags":[],"class_list":{"0":"post-34045","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-net","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>SignalR ile .NET Core &amp; Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi<\/title>\n<meta name=\"description\" content=\"Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve Angular gibi g\u00fc\u00e7l\u00fc teknolojileri SignalR ile birle\u015ftirerek ger\u00e7ek zamanl\u0131 g\u00fcncellemeleri nas\u0131l sa\u011flayabiliriz? Bu makale, sunucudan istemciye sorunsuz veri ak\u0131\u015f\u0131 sa\u011flama s\u00fcrecini ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SignalR ile .NET Core &amp; Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi\" \/>\n<meta property=\"og:description\" content=\"Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve Angular gibi g\u00fc\u00e7l\u00fc teknolojileri SignalR ile birle\u015ftirerek ger\u00e7ek zamanl\u0131 g\u00fcncellemeleri nas\u0131l sa\u011flayabiliriz? Bu makale, sunucudan istemciye sorunsuz veri ak\u0131\u015f\u0131 sa\u011flama s\u00fcrecini ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-10T07:31:18+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"26 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"SignalR ile .NET Core &#038; Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi\",\"datePublished\":\"2025-11-10T07:31:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/\"},\"wordCount\":3475,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\".NET\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/\",\"name\":\"SignalR ile .NET Core & Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-10T07:31:18+00:00\",\"description\":\"Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve Angular gibi g\u00fc\u00e7l\u00fc teknolojileri SignalR ile birle\u015ftirerek ger\u00e7ek zamanl\u0131 g\u00fcncellemeleri nas\u0131l sa\u011flayabiliriz? Bu makale, sunucudan istemciye sorunsuz veri ak\u0131\u015f\u0131 sa\u011flama s\u00fcrecini ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SignalR ile .NET Core &#038; Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"SignalR ile .NET Core & Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi","description":"Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve Angular gibi g\u00fc\u00e7l\u00fc teknolojileri SignalR ile birle\u015ftirerek ger\u00e7ek zamanl\u0131 g\u00fcncellemeleri nas\u0131l sa\u011flayabiliriz? Bu makale, sunucudan istemciye sorunsuz veri ak\u0131\u015f\u0131 sa\u011flama s\u00fcrecini ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.","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:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/","og_locale":"tr_TR","og_type":"article","og_title":"SignalR ile .NET Core & Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi","og_description":"Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve Angular gibi g\u00fc\u00e7l\u00fc teknolojileri SignalR ile birle\u015ftirerek ger\u00e7ek zamanl\u0131 g\u00fcncellemeleri nas\u0131l sa\u011flayabiliriz? Bu makale, sunucudan istemciye sorunsuz veri ak\u0131\u015f\u0131 sa\u011flama s\u00fcrecini ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.","og_url":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-10T07:31:18+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"26 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"SignalR ile .NET Core &#038; Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi","datePublished":"2025-11-10T07:31:18+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/"},"wordCount":3475,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":[".NET"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/","url":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/","name":"SignalR ile .NET Core & Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-10T07:31:18+00:00","description":"Modern web uygulamalar\u0131nda kullan\u0131c\u0131 deneyimini zirveye ta\u015f\u0131mak i\u00e7in anl\u0131k veri ak\u0131\u015f\u0131 hayati \u00f6nem ta\u015f\u0131r. Peki, .NET Core ve Angular gibi g\u00fc\u00e7l\u00fc teknolojileri SignalR ile birle\u015ftirerek ger\u00e7ek zamanl\u0131 g\u00fcncellemeleri nas\u0131l sa\u011flayabiliriz? Bu makale, sunucudan istemciye sorunsuz veri ak\u0131\u015f\u0131 sa\u011flama s\u00fcrecini ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/signalr-ile-net-core-angular-gercek-zamanli-veri-guncelleme-rehberi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"SignalR ile .NET Core &#038; Angular: Ger\u00e7ek Zamanl\u0131 Veri G\u00fcncelleme Rehberi"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34045","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34045"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34045\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34045"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34045"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34045"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}