SignalR’ı Derinlemesine İnceleme

Tüm icatlar ihtiyaçtan doğar. Internet dünya’sının kanayan yarası olan Real Time uygulamalar ya çok resource harcıyordu (clientların belli zaman aralıkları ile server’a ajax post ile request atması(Ajax long polling) ki düşünün 100000 user’ın 10sn’de bir request attığını :) ) yada belli zaman aralıkları ile aynı online gazetelerde olduğu gibi sayfanın yenilenmesi gerekiyordu. Yine bir başka örnek de LES sınavının online olduğunu düşünün; herkes aynı zamanda başlıyacak ve bitirecek. İşte SignalR bu gibi sorunlar için gerçek zamanlı (Real Time) çözüm sunan bir framework’tür.

Yaptığı iş Abstraction Over Transport’ tur. Yani client’daki javascript’i server side’dan çağırmak yada diğer adı ile RPC.Mesela alttaki örnekte kalsik bir chat uygulaması görmekteyiz. Kodları şimdilik çok da dikkate almadan önce yeşil ile belirtilen kısmda client’da click event’inden sonra serverdaki SendMessage() çağrılmıştır ki bu bilmediğimiz birşey değil.Yani klasik ajax post. Ama sonra işler karışıyor:)Serverdaki SendMessage() methodu da  tüm clientlar’daki addMessage() function’ını çağrıyor. İşte bütün mesele budur.

chat02

Image Source: http://www.popkram.com/blog/wp-content/uploads/2012/03/chat02.png

Bu işlem için eğer browser izin veriyorsa yani HTML5 destekliyorsa WebSocket kullanır. Eğer desteklemiyor ise aşağıdaki durumlarla karşılaşılır:

  • Internet Explorer 8 veya daha öncesi is Long Polling yapılır.
  • Connection sırasında jsonp Parametresi true olarak atanmış ise gene Long Pooling yapılır.
  • Cross Domain’de SignalR endpoint ile host edilen sayfanın domain’i aynı değil ise:

Server, Client Websocket’i desteklemez ise ve client CORS (Cross-Origin Resource Sharing) desteklemez ise Long Polling yapılır.

  • Eğer client ve server Websocket’i  desteklemez ise Server Sent Events desteklenir ise kullanılır.
  • Server Sent Event  desteklenmez ise Forever Frame denenir.
  • Forever Frame’de olmaz ise en son çare Long Polling yapılır.

what_is_signalr_invocation2

Image Source: https://www.researchgate.net/figure/Client-Server-connection-24_fig8_295257525

Artık öreneğimize geçebiliriz:

Bir borsa sitesi düşünün client tarafında kağıt değerleri izlenecek. Server tarafında ise kağdın değeri değişitirilince sonuç tüm clientlara pushlanacak.

Önce Modelimizi aşağıdaki gibi oluşturalım.

HomeController’de dummy data önceden oluşturulmamış ise cache atılarak datayı aşağıdaki gibi view’a gönderelim.

Şimdi Index.chtml’imizi yani View’ımızı aşağıdaki gibi kodluyalım.

Aşağıdaki gibi bir ekranı çıktısı almış olduk:

screen

Şimdi bir de Admin ekranı, yani datanın değiştirileceği kısmı aşağıdaki gibi kodluyalım.

HomeController:

Cms.cshtml:

Admin ekran çıktısı aşağıda görüldüğü gibidir.

cms

Şimdi değişiklik yapıcağımız satırdaki Güncelle butonuna basınca server sidedaki methodumuzu tetikleyeceğiz.

Öncelikle sayfamıza gerekli scriptleri aşağıdaki gibi koyuyoruz.

Dikkat ederseniz alttaki gibi bir script var.Aslında böyle bir script yok. Çalışma anında signalR tarafından oluşturuluyor.Buna magic script diyorlar:)

Bunun üzerinde daha sonra gene konuşacağız.

<script src=”@Url.Content(“~/signalr/hubs”)”>

Şimdi Cms.chtml’imizde Client tarafındaki DataModelimizi aşağıdaki gibi oluşturalım. Bu server side’a push edeceğimiz datayı tutacak:

Şimdi de Güncelle butonuna basılınca client side tarafında çağrılan upData() functionunu aşağıdaki gibi kodluyalım:

Buraya kadar değişiklik yapılan datayı, ilgili model’e doldurduk.Şimdi asıl işi yapacağımız kısma geldik. Tam bu noktada pause basıp öncelikle control tarafını(Server)’ı yazmak istiyorum.

İlk başta signalR’ın çalışması için Startup.cs’e alttaki configuration’ı yazalım.

Şimdi HomeControl kısmına alttaki kodu yazalım:

Yukarıda görüldüğü gibi Microsoft.AspNet.SignalR.Hub sınıfından türetilmiş bir Borsa sınıfımız var. public class Borsa : Hub

Bir de UpdateData() adlı bir methodumuz var.İşte bu method Client Side tarafından Güncelle butonuna basılnca çağrılacak olan methoddur.

Cache’den isme göre var olan datayı çekip gönderilen değiştirilmiş data ile güncelleniyor.Ama hepsinden önemlisi sonunda client taraflı Index.cshtml’deki addData() function’ı çağrılıyor.

Clients.All.addData(data);

Şimdi Cms.chtml’e geri dönelim ve değişen datanın server side’a HomeController’a atılmasını UpdateData(DataModel data)‘nın çağrılmasını yazalım.

Öncelikle hub objectimizi oluşturalım:

Javascripteki borsa bizim HomeController’daki Hub’dan türeyen clasımız. public class Borsa:Hub

$.connection.hub.start() ile server ile bağlantı başlar.Detayına ilerde giricez.

upData() function’ı nı şu şekilde güncelledik:

 messagehub.server.updateData(Data);

server taraflı çalışacak UpdateData(Data) methodu çağrılır.Yani serverdaki demin yazdığımız UpdateData(DataModel data) methoduna karşılık gelmektedir.

Şimdi size ÇOK ÖNEMLİ bir not.Dikkat ettiyseniz serverdaki method ismi ile client’dan çağrılan isimlerde büyük küçük harf  farklılıkları var.Bunu nasıl belirliyicez?

Server side tarafında Hub’classı içinde kullandığımız methodların client side tarafındaki karşılıklarını dinamik oluşan

<script src=”@Url.Content(“~/signalr/hubs”)”></script>

içinden arıyarak orda nasıl oluşturuldu ise client’a aynı isimle koymamız gerekmektedir. Örnek ekran görüntüsü aşağıdadır.

hub2

Şimdi Index.cshtml’deki addData() function’ını aşağıda görüldüğü gibi yazalım.

Dikkat edecek olursanız  messagehub.client.addData = function (data) { şeklinde client’da çalışacak addData() function’ı tanımlanır.

Script’in amacı, değişen satırın ufak bir animasyon ile gizleyip yeni datalar ile tekrar gösterilmesidir.

cms

Bunun yanında signalR’ın biraz pekişmesi için cms ekranına aşağıdaki örnekte olduğu gibi bir dropdownlist koyalım.Seçtiğimiz resme göre index ekranının background’ı o anda açık olan tüm clientlar için değişir.

Cms:

Ve dropdown değiştiğinde clientlarda tetiklenecek changeBG() functionını yazalım:

Index.cshtml’deki changeBG() function’ı aşağıda görüldüğü gibidir:

Böylece  Cms’ekranında combo’da change eventi tetiklenince tüm clientların arka resmi aşağıdaki ekran çıktısında görüldüğü gibi değişir.

Untitled

İlerde serverlarımızı scale yaptığımızda yani çoklattığımızda ilgili serverlara bağlı tüm clientlara nasıl erişebileceğimize bakıcaz.Mesela 10000 kişinin 5 server’a dağılmış bir chat uygulamasında yazıştığını düşünün.

1.serverdaki bir client yazı yazdığı zaman 5.serverdaki client bundan nasıl haberdar olucak.İşte bu kurtu içinize düşürdükten sonra makaleme son verebilirim:)

Yeni bir makalede görüşmek üzere herkese hoşçakalın.

Not:Örnek Url (İptal): http://borsasignalr.azurewebsites.net/  ve  http://borsasignalr.azurewebsites.net/cms

GitHub: https://github.com/borakasmer/SignalrExchange

Source: http://www.popkram.com/blog/2012/03/building-a-little-chat-for-episerver-using-signalr/,

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

53 Cevaplar

  1. Romairo dedi ki:

    SignalR , Microsoft’un realtime altyapısıymış. Başlangıçta ASP.Net ile kullanılan.. gibi bir giriş olmadığı ve sonradan ASP.Net kodları ile birlikte görmeye başlayınca bu sonucu kendim çıkardım :)
    Sonuçta MS’in realtime altyapısız olması düşünülemez, MS’deki geliştiriciler bunu en iyi şekilde geliştirmiş. Ancak realtime web alanında node.js ve son 1 yılda yaygınlaşan Go da çok kullanışlı. MS zaten bazı kodlarında node.js’i de kullanıyor.

  2. borsoft dedi ki:

    Microsoft VisualStudio’da signalR’ı kullanıyor doğrudur.Mesela view’da,css veya js’de değişikliği gidildiği zaman o an açık olan tüm clientlardaki o sayfa refresh olabiliyor.
    Gelecek yazım node.js’in yakın akrabası typescript üzerine olucak.O zaman belki bazı konularda size ışık tutabilirim.
    İyi günler

  3. Uğur dedi ki:

    Hocam Merhabalar,

    Yazılarınız gerçekten çok iyi. Bu kadar uğraşıp emek verdiğiniz için teşekkür ederim.

    SignalR ile yeni tanıştım. Bir şeyler öğrenmeye çalışıyorum. Bir soru var kafamda cevaplarsanız sevinirim.

    SignalR serverdan clientlara push edilme olayı anladığım kadarıyla. Bu örnekte olduğu gibi bütün client’lar etkileleniyor . Peki sadece belli kullanıcıların etkilenmesini istersek ne yapmamız gerekir. Aklıma bir yol geldi ama iyi bir çözüm olduğunu sanmıyorum. Şöyle ki ;

    Server bütün clientlara push etmeye devam edecek fakat client tarafında session bazlı bir kontrolümüz olacak. Yani sadece ilgili kullanıcılar değişikliği görebilecek. Ama aslında tüm clientlara da o bilgi gitmiş olacak. Bazılarında görünecek bazılarında görünmeyecek.Böyle bir yol izlenebilir mi? Yada bunun en doğru yolu nedir?

    • borsoft dedi ki:

      Selam Uğur;
      Öncelikle güzel yorumların için teşekkürler.
      Belli kullanıcılara trigger işlemi için düşüncen özellikle performans anlamında büyük sorunlara neden olur. Ekip bunu düşünmüş ve Clientlarda gurup özelliğini eklemiş. Yani gelen client’ı bir guruba ekleyip, sadece bir guruba push edebilirsin. Örnek kod aşağıdaki gibidir.

      İyi çalışmalar.

      public override Task OnConnected()
      {
      Groups.Add(Context.ConnectionId, “Group1”);
      JoinRoom(“Group1″);
      }

      public async Task JoinRoom(string groupName)
      {
      Clients.Group(groupName).addChatMessage(groupName+”gurubuna yeni bir kişi katılmıştır.”);
      }

      • mes dedi ki:

        Peki bu kodların view tarafındaki javascript kısmı nasıl olmalı??

        • borsoft dedi ki:

          Selam Mesut,

          İlgili codelara yandaki adresten ulaşabilirsin.

          İyi çalışmalar.

          • Kaan dedi ki:

            Merhaba Bora, öncelikle tebrikler sıkı takipçilerinden oldum açıkcası.. Yandaki adresten kasıt nedir bulamadım veya göremedim mi acaba?

          • borsoft dedi ki:

            Teşekkürler,

            Yandaki adresten cümlesi nerede geçiyor acaba?

  4. Fatih dedi ki:

    Hocam merhaba :) Yazınız güzel elinize sağlık ilk araştırmamı makaleniz üzerinden yaptım. Amma velakin :) bu kadarlık bir kullanım artık işimi görmüyor :( Bunun için bir kaç sorum olacak :)

    1-SignalR Client Id yi her zaman “connection.hub.start()” olduğunda mı üretir ve her durumda sayfa refresh olmadıkça yeni bir clientId üretmez mi?(callback/ajax request kullandığım yerler için)

    2-Aşağıdaki bağlantıda tarayıcılara göre max limitleerin olduğu bir tablo bulunmaktadır.
    http://www.browserscope.org/?category=network&v=top
    Örneğin chrome kullanırken bazen “websocket bekleniyor” gibi bir yazı geliyor ve sayfa açılmıyor. Acaba kullanılmayan bağlantıları sonlandırmadığımız için mi böyle bir sorun çıkıyor? sonlandırmak için ne yapmalıyız?

    myHubProxy.client.stopClient = function() {
    $.connection.hub.stop();
    };
    Gibi bir yol mu izlemeliyiz? Ne zaman kullanılmayan(sayfadan ayrılan) bağlantıları nasıl sonlandırabiliriz.

    Teşekkürler :)

    • borsoft dedi ki:

      Selam Fatih,
      Öncelikle teşekkürler.

      1-)ClientID üretimi connection.hub.start()’anında olur. Yeni bir client Connect olurken ona özel ID yaratılır. Aynı Sql’de yeni bir kayıt yaratırken @@identity ile yeni oluşan ID almak olarak düşünebilirsin. Refresh olmadan şu an için üretilemiyor diye biliyorum. Ama product guruba bunun ile ilgili bir geliştirme var mı diye sorucam…

      2-)Sayfadan ayrılan yani session’ı düşen client’ın connection’ı hemen kaybolur. Senin ayrıca düşürmene gerek yok. Ama düşürmen gerekirse yazdığın kodlar evet geçerli..Refresh zamanında bile disconnect işlemi olur.
      Hatta düşüp düşmediğini alttaki kod ile yakalayabilirsin.

      İyi çalışmalar.

      public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
      {
      if (stopCalled)
      {
      Console.WriteLine(String.Format("Client {0} explicitly closed the connection.", Context.ConnectionId));
      }
      else
      {
      Console.WriteLine(String.Format("Client {0} timed out .", Context.ConnectionId));
      }

      return base.OnDisconnected();
      }

      • Mert dedi ki:

        burda browserın kapatıldıgını veya reflesh oldugunu anlayabilir miyiz?

        • borsoft dedi ki:

          Evet tabi ki anlayabiliriz. Refresh veya kapatılma durumunda
          Signalr Hub sınıfının OnDisconnected() methodu tetiklenecektir.

          İyi çalışmalar.

  5. Gökhan dedi ki:

    Hocam elinize sağlık çok güzel anlatım olmuş. Ancak rica etsem asp.net için c# anlatabilir misiniz?
    Mvc kullanmıyorum henüz, projemde çok lazım bu sistem.

    • borsoft dedi ki:

      Selam Gökhan,

      Öncelikle teşekkürler. Gerçek hayat için MVC öğrenmeni tavsiye ederim. 2. olarak farklı konularda yazdığım için bu konuyu bir daha yazmaya malesef vaktim yok. Ama sen Asp.Net’de MVC’den yola çıkarak kendin yazmaya çalış. Takıldığın yerleri de Mail yolu ile bana sor.

      İyi çalışmalar.

  6. Cihan dedi ki:

    süper bir makale teşekkürler

  7. Umut dedi ki:

    Hocam Merhabalar..
    Güzel bir makale olmuş, bu yüzden bir teşekkür de ben eklemek istiyorum.

    ASP.NET ile hazırlanmış bir e-ticaret sitesi için Native Android uygulaması hazırlıyorum. Uygulamanın bölümlerini Realtime olarak yapmaya niyetlendim ve bu sebepten ötürü SignalR ile tanıştım.

    Bu konuyla ilgili Türkçe kaynak maalesef yok denecek kadar az.(Hatta SignalR’ın Android ile kullanımı konusunda yabancı kaynak bulmakta pek kolay olmadı) Bu noktada makaleniz ilaç gibi geldi diyebilirim :)
    Sonuç olarak istediğimi yaptım ve mutluyum.

    Araştırma yaparken kafama takılan bir kaç soru oldu. Bu konuda yardımcı olursanız daha da mutlu olacağım. :)

    Sorular :
    1-) Android Client tarafında Server Sent Events kullanmaktayım. Bunun yerine Long Polling kullanma özgürlüğüne de sahibim. Fakat böyle bir seçim yapmanın bana performans açısından bir avantajı yada dezantajı olur mu? (Yada hiç dokunmayıp böyle devam mı edeyim?)

    2-) Genel olarak bakıldığında Geliştiriciler çoğunlukla Restful Servisi kullanmakta.. Merak ettiğim ise neden Geliştiriciler SignalR yerine Web Api tercih etmekteler? Restful Api’lerin performansı SignalR’a göre çok daha mı iyi? Yoksa bu durumun tek nedeni kaynak yetersizliği yada SignalR’ın biraz daha uğraştırıcı olması mı?
    (Çünkü sürekli GET-POST işlemi yapmak yerine Real Time veri akışı uygulamayı daha hızlı hale getirir diye düşünüyorum.)

    3-) Yoğun veri alış-verişinin olduğu bir uygulamada SignalR kullanımının dezavantajları var mıdır? Herhangi bir veri bozulması durumu söz konusu olur mu? (İnternette dolanırken böyle bir soruya denk gelmiştim de cevabına rastlamamıştım)

    İyi çalışmalar..

    • borsoft dedi ki:

      Selam Umut,

      Öncelikle güzel yorumların için teşekkürler. Makalemin işine yaramasına çok sevindim.

      1-)Long Polling performans kaybına kesin yol açar :)

      2-)SignalR ve WebApi Restfull birbirinden çok farklı konular. SignalR serverdan clientlara bir push işlemi. Restfull ise client’dan server’a cross domain’e düşmeden get post işlemi. Eğer canlı data ve bunun gösterimi senin için hayati bir önem taşıyorsa mesela monitöring ekranları yapıyorsan tabiki socket teknolojisi kullanacaksın. Ciddi bir performans harcar. Yok hayır ben timer ile her 1 dakikada bir client tarafdan ilgili servise request çekerim ve gelen dataya göre client’daki datayı güncellerim dersen WebApi restFull. Tabiki signalR’a göre ciddi bir performans KAZANCI ve çok az kaynak tüketimi olur. Ama bu örnekde olduğu gibi en yakın datayı 1 dakika geriden takip edersin. Umarım biraz olsun aydınlatabilmişimdir.

      3-) Yoğun tarifikte signalR ile veri kaybı yaşamaz ama ciddi bir tırafik alacağın için Redis veya Azure üzerinde scale yani 4-5 sunucu üzerinde signalR paralel programing yapman gerekir.

      İyi çalışmalar. Hoşçakal.

  8. Emre dedi ki:

    Hocam , signalr ile chat sistemini bir web api üzerinden yapmak istiyorumda nasıl bağlanıp veri alış verişi yapabilirim.
    Teşekkür ederim

    • borsoft dedi ki:

      Chat sisteminde WebApi’yi ancak mesajları kaydetmek için kullanabilirsin. Ama yapma.

      Mesajlaşma için Socket kullan(SignalR, NodeJS) gibi. Kaydetmek için de bir microservice içerisinde RabbitMQ veya Kafya gibi yapılar kullan.
      İyi çalışmalar.

  9. Ezgi dedi ki:

    Merhaba hocam, uygulamamda kullanıcı birden fazla oturum açtığında önceki oturumlarını bir alert ile uyarıp kapatmak istiyorum. Ancak bunu tek bir kullanıcıya iletecek şekilde ve kendi kullanıcı modelimle uyumlu hale nasıl getirebilirim? Teşekkürler.

    • borsoft dedi ki:

      Selamlar Ezgi,

      Bunu tek bir kullanıcıya göndrebilirsin. Aslında her kullanıcıya ait UserID ve ConnectionID’i bir Redis gibi distributed cache’de tutar isen, daha sonra kullanıcının diğer UserID’lerine erişin ilgili connectionID ile erşip:
      Clients.Client(Context.ConnectionId).onMessage(
      new Message{MessageText}
      );
      Şeklinde uyara bilirsin. Ya da kullanıcıyı belli bir User Grubua ekliyip gurup mantığı ile de çalışabilirsin.

      iyi çalışmalar.

  10. Okan DUNAY dedi ki:

    Hocam selamlar,

    Buraya yazmak doğru olacak mı bilemedim ama makaleniz ile ilgili olduğu için sizden yardım ve bilgi rica ediyorum.

    WebApi ile SignalR aynı projede ,harici bir web uygulamasından bağlantı sağlayabiliyorum OnConnected() metoduna debug ortamında ulaşabiliyorum, fakat magic script oluşturulurken içerisindeki metotlar oluşmuyor

    proxies[‘WareHouseHub’] = this.createHubProxy(‘WareHouseHub’);
    proxies[‘WareHouseHub’].client = { };
    proxies[‘WareHouseHub’].server = { // metodları oluşturmuyor
    };

    script nasıl oluşturuluyor, nelere gereksinim duyuyor, client tarafın katkısı var mıdır oluşturulurken gibi sorularım var, ayrıca ek olarak webApi olduğu için sadece help sayfası mevcut route ayarları önemli midir, bu scriptin oluşumunda

    • borsoft dedi ki:

      Selamlar Okan,
      Öncelikle bu script’i neden manuel oluşturmak zorundasın onu anlayamadım. 2. Magic script’i elle oluşturmak, evet hiçbirşey imkansız değil ama bu ona diğerlerinden biraz daha yakın :)

      WebApi Servisi ile SigalR’ı zaten konuşturmuşun..
      Olmadı derdini anlatıp bir github verirsen, daha basit bir yolla sorununu çözmeye çalışırız.

      Hoşçakal..

  11. Ayşe Sayarı dedi ki:

    Merhabalar, ben Akif Tuncel Meslek lisesini yeni bitirdim ve kendi çabamla yazılım sektöründe ilerlemek için çaba gösteriyorum.
    Makalenizi okudum; Signal R teknolojisi üzerine deneyim sahibi değilim, sadece şunu danışmak istiyorum;

    Clients.User(ConnectionId).send(message); (bu doğru bir syntax mı)

    Dilim döndüğünce stackoverflow a sordum, bana verilen yanıtlar yüzeysel idi,

    Signal R nin kendine ait bir ConnectionUser tablosu olduğu, Start Hub esnasında bağlanan kullanıcı dolayısıyla oluşturulan ConnectionID nin Kendi database imde olan UserID ile birlikte tanıtılması gerektiği ancak bu şekilde

    Clients.User(UserId).send(message); sözdiziminin geçerli olacağı paylaşıldı ama,

    Start Hub esnasında nasıl ConnectionID yi yakalayabileceğim (ki esas sorum bu idi)
    daha sonra da Signal R nin ConnectionUsers tablosuna kendi database imdeki kullanıcı id si ile birlikte nasıl tanıtabileceğimden pek bahsedilmedi

    ConnectionUsers.Add(ErdemBeyUserID, ConnectionID) gibi bir metod mu var anlayamadım açıkçası (bulamadım da bu saat oldu : 4:20)

    Çok eşekkür ederim.

  12. SignalR dedi ki:

    Bora Hocam selamlar,

    asp.net webform üzerinde signalr kullanımı zor gibi geldi. Yanılıyor muyum? Örneğin öğrenci listesini gridview ile yayınlıyorum. update panel içerisine aldım ve timer ile 1 dakika da bir tetikliyorum. Signalr’a dönüştürmeye çalıştım oldukça zor geldi. Aydınlatabilirseniz çok sevinirim.

  13. Yusuf dedi ki:

    Emeğiniz ve paylaşımınız için çok teşekkürler. Yukarıda yazıda geçen bazı kısımlar kod olatak gösterilmemiş(Layout.csgtml, style dosyaları, buton vs.) Daha detaylı inceleyebilmek için projenin kaynak kodlarımı paylaşmanız mümkün mü acaba?

  14. Yusuf dedi ki:

    Anlatımınız ve paylaşımınız için teşekkürler.

    …select itm).ToList().ForEach((DataModel b) => this.setValue(b, data.Name, data…

    Satırında bulunan setValue fonksiyonu nerede oluşturuluyor acaba?
    Kodları daha detaylı inceleyip daha iyi anlayabilmek için kaynak kodları paylaşmanız mümkün mü acaba?

    • borsoft dedi ki:

      Selam Yusuf,
      Öncelikle setValue() methodunu makaleye koymamışım. Şu an güncelledim. Bu zamana kadar kimsenin fark etmemesi çok enteresan. Öncelikle bu düzeltme için teşekkür ederim.
      Her ihtimale karşı method’u yoruma da ekledim. Codeları da yakın zamanda GitHub’a atarım.

      İyi çalışmalar.

      private void setValue(Model list, string name, double dun, double dusuk, double hacimlot, double hacimtl, double ort, double son, double yuksek, double yuzde)
      {
      list.Name = name;
      list.Dun = dun;
      list.Dusuk = dusuk;
      list.HacimLot = hacimlot;
      list.HacimTl = hacimtl;
      list.Ort = ort;
      list.Son = son;
      list.Yuksek = yuksek;
      list.Yuzde = yuzde;
      }

  15. Emre ÜRÜN dedi ki:

    Gerçektende faydalı bir makale olmuş. elinize sağlık. SignalrRı MVC 4 ile yazılan bir projede chat modülü için kullandım. Ancak bu modülün aktif olup olmayacağını bir ayara bağlamam gerekiyor. Ancak signalR’ın ayağa kalkmamasını bir türlü sağlayamadım.
    İnternette de maalesef bir çözüm bulamadım. signalR için yazdığım bütün kodları kapattım ancak hala chrome’da network hareketlerine baktığımda “poll?transport=longpolling” ve send?transport=longpolling” ile başlayan kayıtlar görüyorum.
    SignalR ın web.config deki bir ayara göre çalışıp çalışmayacağını nasıl belirtebilirim.

    Yardımcı olursanız sevinirim

    • Emre ÜRÜN dedi ki:

      Network listesinde gördüğüm hareket vs browser link’ten kaynaklanıyormuş. Ben olayı yanlış yorumlamışım. Benzer hatayı yaşayan olursa çözüm olsun diye belirteyim dedim. :d
      Kusura bakmayın.

  16. serdar dedi ki:

    merhaba chat uygulaması yaptım ilk 5-6 dk normal ama sonra kırmızı olarak
    Error: SignalR: Connection must be started before data can be sent. Call .start() before .send()
    hatası alıyorum durduk yere bunu veriyor çözümü bulamadım

    ben bu şekilde start kullanıyorum ama microsoft sitesinde “birden fazla method kullancaksanız proxy kullanmalısınız gibi bir benzetme var.. bunla proxy arasındaki fark nedir ? uygulamam içinde birden fazla method kullanıyorum bundan dolayımı bağlantı kopuyor

    var chatHub = $.connection.chatHub;
    registerClientMethods(chatHub);
    $.connection.hub.logging = true;

    $.connection.hub.start().done(function () {

    son olarak client lar belli zaman içinde timeout oluyor baktığımda
    public override Task OnReconnected()
    var ancak burada bağlantısı kopan id artık var olmadığından yeni id alması gerekmezmi
    disconnected > OnReconnected > connected
    bu sıralama yada süreç nasıl olmalı

    ve üsteki hatayı almadığım zamanlarda ise
    ailed: WebSocket is closed before the connection is established.
    chrome da hatasını sarı uyarı olarak alıyorum

    teşekkürler

    • borsoft dedi ki:

      Selamlar Serdar Bey,
      Aşağıda konu ile ilgili client side taraflı kullandığım bir çözüm bulunmaktadır.

      connection = $.hubConnection(url, { useDefaultPath: false });

      connection.disconnected(function () {
      setTimeout(function () {
      alert(“Disconnected”);
      connection.start();
      }, 5000);
      });

      İyi çalışmalar.

  17. serdar dedi ki:

    tekrar merhaba bora bey aslında ne büyük sorunum ise bir kullanıcı f5 yaptığında disconnected olması tamam normal.. burada kullanıcı array den ilgili kullanıcıyı remove ediyorum tamam bağlantısı siliniyor ama saçma olan şu
    ben A kullanıcısında f5 yapıyorum disconnected oluyor akabinde disconnected event tekrar hemen debug düşüyor ve karşıdaki kullanıcıyıda disconnected ediyor.. ?

    public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
    {
    var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
    if (item != null)
    {
    ConnectedUsers.Remove(item);

    var id = Context.ConnectionId;
    Clients.All.onUserDisconnected(id, item.UserName);

    }
    return base.OnDisconnected(stopCalled);
    }

    • M. Ali dedi ki:

      Aynen benim takıldığım konuda bu oldu, refresh de anlık disconnect olup connect oluyor nasıl bir yol izleyebiliriz acaba? Birden fazla sekmede oluşan id leri bir liste alıp connectionu korudum user listeden sildirmedim ama tek sayfada refresh de bu problem var karşı kullanıcıya kötü görünüyor bi var bi yok beyin fırtınası yapabiliriz bi el atalım lütfen bekliyoruz :)

      • borsoft dedi ki:

        Selamlar Ali,
        Refresh demek kullanıcının ayrılması ve yeni connectionID alarak, tekrardan bağlanması demektir. Bir static liste ya da redis gibi bir cache yapısı kullanarak Userların connectionID’lerini Nickleri ile beraber sakla. Disconnect durumunda ayrılan Nick’e bağlı connectionID’ye karşılık gelen yeni connectionID’yi tut. Ve bu yeni connectionID’yi signalR ile diğer clientlara bildir. Böylece iletişim hiç kesilmede,n aynı kişi ile konuşma devam edilebilir.

        iyi çalışmalar.

  18. Mehmet dedi ki:

    1 sene geçti GitHub gelmedi mi (:

  19. Oğuzhan SARI dedi ki:

    Merhaba Bora bey, ben CMS imde sitemap güncellemesi işlemini aşamalı olarak yapmak istiyorum.
    CMS de sayfalar,haberler,ürünler,hizmetler,çözümler,araçlar,blog yazıları,sık sorulan sorular, kategoriler(haber ve blog için), galeriler,şubeler bölümleri var ve her içerik için seo linkleri mevcut. Bunlar için sitemap oluşturmak istiyorum. Yöneticinin sitemap oluştura tıkladıktan sonra işlemin başarılı olup olmadığını öğrenmesi için o sayfada beklemesini istemiyorum.
    Arka planda bu işlemi signalr ile geçrekleştirebilir miyim. (Bir işlemi başlatıp (jquery post) sayfayı kapat-sakta zaten işlem sunucu tarafında işlenmekte.)

    Benim istediğim veritabanına işleme ait ID verip her modül için işlem kaydı oluşturmak.
    (Haber sitemap oluşturma *başladı, *bitti (başarılı), *bitti (başarısız) gibi.)
    Ve bunları panelde sağ alt tarafta küçük bir absolute ekran da her işlem kaydı yapıldığında göstermek istiyorum.
    Zaten signalr db ye post olduğunda tetikleyip veriyi getiriyor. Konuyu detaylı ilettim. Daha net fikir elde edebilmek için bilgilenmenizi istedim.

    Arka plan işlemlerinde öneri ve kilit noktalar hakkında bilgi verirseniz de sevinirim.
    Teşekkürler.

    • borsoft dedi ki:

      Selam Oğuzhan bey,

      Bu bir soru değil gibi aslında:) Tam bir danışmanlık işi gibi birşey. İşin şakası bir yana gerçekten işin içine girmeden, alt yapı ve sistemi bile görmeden birşeyler söylemek ne doğru olur ne de bir makalenin altında yazılacak kısa bir cevap ile böyle bir projedeki riskler öngörülebilir..

      İyi çalışmalar.

  20. aysu dedi ki:

    Merhabalar bu yazınız için çok ama çok teşekkürler bu kadar bilmek başka paylaşmak bambaşka güzel. Benim sorum şu, ,twitterdan stream ile canlı olarak tweetleri almak istiyorum signalr ile yapabilirim gibi geldi. Vaktinizi çok çalmadan bana ufak bir yol gösterebilirseniz çok sevinirim teşekkürler.

  21. isimsiz dedi ki:

    İnsanlara böyle öğretmeniz o kadar güzel bir şey ki . Yolunuz hep açık olsun çok teşekkürler

  22. denemeyanılma dedi ki:

    merhabalar, UpdateData fonksiyonunda httpcontext kısmında ; An object reference is required for the non static field,method,or property Controller.Httpcontext diye hata veriyor çözemedim yardımcı olur musunuz ?

    • borsoft dedi ki:

      Selamlar,

      httpcontext nesnesini ya da kullanıldığı methodu başında “static” diye muhtemelen tanımlamışınız.
      Onu kaldırmanız gerekmektedir.
      Olmadı kodu Github’a atarsanız ordan da bakabilirim.

      İyi çalışmalar.

  23. Mustafa dedi ki:

    Bora bey Selam
    Signalr redis ile scale etme hakkında makaleniz var mıdır. Ayrıca bu yapıyı web.api core da kullansak bir sıkıntı olurmu?

  24. Murat YEŞİLBAŞ dedi ki:

    Güzel yazı ancak; aşşağıda değiş aşağıda olmalı.

    • borsoft dedi ki:

      Teşekkürler,
      Hepsini düzelttim :)

      • Murat YEŞİLBAŞ dedi ki:

        Hoş bende kaş yaparken göz çıkartmışım =)

        GitHub örneğinizde Owin sınıfının girişini belirtmemişsiniz. (Startup.cs)
        Sanırsam 2.0 sürümünden itibaren OWIN sınıfı olmadan SignalR çalıştıramıyorsunuz.
        Magic Script oluşmuyor.

  25. ilyas dedi ki:

    Identity ile oturum acan kullanicinin ID sini client.user(ID).getmessage seklinde kullandigimda sonuc alamiyorum. Veritabanimdaki userId ye mesaj atmak istiyorum sadece bunu nasil yapabilirim? Yardimci olursaniz sevinirim.
    iyi calismalar.

    • borsoft dedi ki:

      Selam Ilyas,

      Bir tanem static Dictionary ya da Redis üzerinde SignalR OnConnected() Methodunda UserID’ye karşılık gelen ConnectionID’yi tutabilirsin. Daha sonra Redis’den ilgili userId’ye göre ConnectionID’yi alıp sadece ona ==> await Clients.client(UserId).SendAsyc(“Getmessage”,yourMessage); şeklinde atabilirsin.

      İyi çalışmalar.

  26. Ali dedi ki:

    Hocam Merhabalar,
    SignalR ve Rabbitmq ile excel tarzı raporlar verilebilecek bir yapı kurmayı deniyorum. Size sormak istediğim şu, kullanıcı rapor ala bastığında kuyruğa eklenilecek, işlem bittiğinde de signalR ile ilgili kullanıcıya uygulama üzerinde bildirim vermek istiyorum. Burada yapılan projeyi birden fazla server üzerinde yayınlanması, load balancer gibi cihaz olması bütün kullanıcılara ulaşma yada ilgili kullanıcıya ulaşmada sorun olur mu? ilk bağlantıyı 1. sunucuya yaptı. kapattı açtı load balancer 2. sunucuya bağlandırdı.
    2. sorum da bütün kullanıcılara uygulama üzerinden mesaj göndersem sadece benimle aynı sunucuya bağlı kullanıcılar mı görür hepsine mesaj gider mi?
    Bilgileriniz ve yazılarınız için ayrıca teşekkür etmek isterim. İyi çalışmalar

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.