«

wrz 24

SignalR – pierwsze kroki

Zanim przejdę do tytułowej biblioteki chciałbym, aby czytelnik odpowiedział na następujące pytanie. Dlaczego tworzenie stron internetowych jest trudne?
Jakieś pomysły? Moim, zdaniem największą trudnością jest wspieranie wielu różnych przeglądarek, które z kolei w zależności od wersji wpierają lub nie pewne standardy. Króluje tutaj oczywiście IE, w którym wszystko musi być inaczej, na szczęście powoli to się zmienia. Z powyższym problemem dobrze radzi sobie jQuery, która zdejmuje z barków programisty część odpowiedzialności za obsługę wielu przeglądarek. Innymi słowy, to co napiszemy w jQuery zadziała niezależnie od przeglądarki. Jednak jQuery nie jest odpowiedzią na wszystkie problemy.

Większość komunikacji, między stroną www(klientem) a serwerem opiera się o request – response, czyli klient wysyła żądanie na serwer (synchronicznie lub asynchronicznie) – natomiast serwer odpowiada zwracając rezultat np. autoryzując użytkownika. W takiej komunikacji to zawsze klient inicjuje komunikację. Co jednak, gdybyśmy chcieli odwrócić komunikację? Chcielibyśmy wysłać do wszystkich klientów wiadomość, że zaszła jakaś zmiana na serwerze o której powinni wszyscy wiedzieć np. zalogował się nowy użytkownik do chatu lub pojawiła się nowa promocja w sklepie internetowym.
Komunikacja taka nosi nazwę push lub broadcast.

Jak zrealizować taką komunikację? W Wcf można zastosować duplex a jak to zrobić na stronie www. Jednym z takich mechanizmów jest longpolling – mechanizm ten symuluje komunikacje w stylu duplex w następujący sposób. Z klienta www wysyłamy żądnie asynchroniczne (ajax) na serwer, jednak serwer nie odpowiada od razu. Serwer odpowie wtedy, gdy pojawi się taka potrzeba. W ten sposób można stworzyć komunikacją, która udaje push. Co jednak, gdy klient zamknie przeglądarkę co się stanie z żądaniem na serwerze? Jak, dać serwerowi znać, że klient jest obecny i jest gotowy, aby odbierać wiadomości? Jak zapisać takie, żądanie po stronie serwera? Czy są lepsze mechanizmy, które nie wymagają ciągłego wysyłania żądań? Które przeglądarki wspierają takie mechanizmy? Jak widać pytań jest dużo, dlaczego to wszystkie pisze. Chciałbym, aby czytelnik uświadomił sobie jaką świetną biblioteką jest SignalR. Dlaczego jest taka świetna? Ponieważ odpowiada na powyższe pytania za nas;) Czas na jakiś przykład.

W przykładzie, wykorzystamy VS2012 projekt typu Asp.Net MVC 4 Web Application. Po utworzeniu takiego projektu, załóżmy że chcemy zrealizować następujący scenariusz: chcemy, aby pewien użytkownik np. admin był wstanie wysłać wiadomość do wszystkich obecnych na stronie. Nie będę tutaj wprowadzał żadnego mechanizmu autoryzacji po prostu dodamy akcję Admin, w kontrolerze Home, która wygeneruje formularz, z którego wyślemy wiadomość do wszystkich.

Kod metody obsługującą akcję, Admin sprowadza się więc tylko do zwrócenia widoku.

Kod widoku dla, tej akcji zawiera na razie tylko pole do wpisania wiadomości i przycisk.
Poniżej kod widoku z pliku Admin.cshtml

Dodajmy teraz referencje do SignalR w naszym projekcie, w tym celu należy wpisać install-package Microsoft.AspNet.SignalR do Package Manage Console. Po zainstalowaniu SignalR utwórzmy katalog Hubs w naszym projekcie a w nim klasę o nazwie AdminHub. Kod klasy poniżej.

Jak widać AdminHub dziedziczy po klasie Hub, która jest zdefiniowana w przestrzeni nazw Microsoft.AspNet.SignalR. Klasa hub zapewnia komunikację pomiędzy klientami a serwerem. Metoda Send zostanie wywołana w odpowiedzi na wciśniecie przycisku Wyślij, w tej metodzie korzystamy z właściwości Clients dzięki, której możemy wywołać metodę showMessage, po stronie klient, którą wkrótce zdefiniujemy. Właściwość Others jest typu dynamic dlatego nie uzyskamy tutaj żadnego Intellisense, a sprawdzenie czy metoda istnieje odbędzie się w momencie próby wywołania jej.
Pora teraz zmodyfikować plik Admin.cshtml, tak aby korzystał z SignalR.

Dodałem tutaj referencje do plików jquery.signalR-1.1.3.min.js oraz do pliku, który jest generowany przez SignalR ~/signalr/hubs, referencja do jQuery oraz jQurery-ui dodana jest w pliku _Layout.cshtml przez mechanizm bundle. Tworzymy tutaj również okno dialogowe, które wyświetlimy po wysłaniu wiadomości. Żeby wysłać wiadomość musimy pobrać obiekt huba, w naszym przypadku jest właściwość adminHub obiektu connection. Nazwa właściwości jest tutaj nieprzypadkowa jest to nazwa klasy AdminHub zapisana w notacji CamelCase. Połączenie z serwerem nawiązujemy poprzez wywołanie metody $.connection.hub.start(). Metoda ta jest asynchroniczna i gdy zostania ona zakończona, czyli połączenie zostanie nawiązane, dodajemy obsługę do zdarzenia click przycisku Wyślij. Następnie wywołujemy metodę send (metoda jest zdefiniowana w klasie AdminHub i zapisana w konwencji CamelCase), do której przekazujemy wiadomość.
Po wysłaniu wiadomości pokazujemy komunikat wiadomość wysłana.

Aby można było nawiązać komunikację za pomocą SignalR należy zrobić jeszcze jedną rzecz mianowicie zmodyfikować odpowiednio tablice tras w następujący sposób.

SignalR do komunikacji używa adresu /signalr metoda RouteTable.Routes.MapHubs() modyfikuje odpowiednio tabele tras, aby ten adres obsługiwany był przez SignalR. W tej chwili mam już mechanizm odpowiedzialny za wysyłanie wiadomości, żaden klient jednak na nie nie czeka. Dodajmy, więc kod klienta. Klient będzie, znajdował się pod adresem /Home/Client. Poniżej kod akcji oraz widoku Client.cshtml

Podobnie jak w przypadku admina, dodajemy referencje do plików jquery.signalR-1.1.3.min.js i signalr/hubs i tworzymy okno dialogowe, w którym znajdzie się otrzymana wiadomość. Żeby otrzymywać wiadomości musimy nawiązać połączenie z serwerem robimy to wywołując funkcje $.connection.hub.start();. Następnie definiujemy funkcje showMessage, która zostanie wywołana przez serwer w klasie AdminHub.

Ok teraz test.

Wszystko działa i w kilka chwil napisaliśmy komunikacją push. SignalR jest rewelacyjną biblioteką, ponieważ sama zajmuje się wybraniem odpowiedniego sposobu komunikacji w zależności jakiej przeglądarki używa klient. Poniżej lista używanych technologii transportu w zależności od przeglądarki.

signalRSupportedBrowsers

Umiemy wysyłać wiadomości z serwera do klientów, ale nie wiemy ilu klientów dostało wiadomość i czy w ogóle ta wiadomość do kogoś doszła. SignalR nie udostępnia powiadomienia o tym czy wiadomość została dostarczona. Można jednak taką rzecz zrobić samemu dodając wywołanie metody serwera po otrzymaniu wiadomości w kliencie. Polecam spróbować samemu wykonać takie ćwiczenie: aby po wysłaniu wiadomości w panelu administratora pojawiała się liczba klientów, do których wiadomość została dostarczona.

Link do źródeł projektu

Podobne posty

  1. Mity o sieci

7 Komentarzy

Skip to comment form

  1. Piotr Ptak

    Bardzo fajne i przyjemne wprowadzenie do SignalR z fajnym przykładem – w końcu w sieci jakiś inny przykład niż czat z wykorzystaniem SignalR :-). Mam nadzieję, że wrzucisz jeszcze jakieś posty z opisem SignalR.

  2. Mateusz

    Dzięki Rafał. Fajnie, że ktoś na blogach zahacza o tematy ważne dla Juniorów. Mam prośbę czy mógłbyś kiedyś jeden wpis poświęcić podzieleniu plików w projekcie? Chodzi mi o to żebyś pokazał jak dobrze rozplanować projekt i gdzie umieścić poszczególne pliki (czyli obrazki w images..itp)

    1. graf

      Ok, będę miał to na uwadze. Niestety rzadko zdarza się tworzyć coś od początku i strukturę projektu dostaje się w spadku. Struktura projektów zależy od wzorców projektowych i architektury użytej w projekcie. Jednym wpisem się tego nie omówi, ale postaram coś ciekawego na ten temat napisać.

  3. Adrian

    Send jest czasownikiem nieregularnym, a jego przeszła forma brzmi sent.

    Swoją drogą świetny artykuł. Bardzo przystępny wstęp do tej genialnej biblioteki.

    1. graf

      No tak, analfabetyzm tutaj propaguje. Dzięki za zwrócenie uwagi.

  4. Mateusz

    Czesc,

    moglbys opisac co nieco o metodzie OnRecconected?

    1. graf

      Niestety nowe obowiązki nie pozwalają mi na prowadzenie bloga, ale mam zamiar do tego powrócić. Póki co jednak proponuje Ci przeczytać artykuł http://www.asp.net/signalr/overview/signalr-1x/hubs-api/handling-connection-lifetime-events

Odpowiedz na „MateuszAnuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Możesz użyć tych znaczników i atrybutów HTMLa: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Current day month ye@r *