W swoim projekcie umieściłem funkcjonalność, na którą czekałem już od jakiegoś czasu. Chodzi o informowanie klienta o statusie jakie ma jego zamówienie i szacowanym terminie realizacji w czasie rzeczywistym i bez przeładowywania strony. Wszystko za pośrednictwem pojedynczej strony, na którą klient jest przekierowywany po wykonaniu zamówienia i kilku linijek kodu w SignalR.
Póki co znajduje się ona na wczesnym etapie i wymaga dorobienia kilku elementów interfejsu, które będą trzymać wszystko w kupie, ale jest to raczej mało istotna rzecz w kontekście całej funkcjonalności dlatego na dzień dzisiejszy ją pomijam. Nie chciałbym również powtarzać pewnych informacji, więc jeśli ktoś nie do końca wie czym jest SignalR, jak działa i jak go używać, to odsyłam do swojego poprzedniego posta na ten temat.
Cała funkcjonalność ma działać w ten sposób, że klient po złożeniu zamówienia (i ewentualnej płatności) jest przekierowywany na stronę ~/Order/OrderStatus/{id} ,która zawiera prostą informację, że zamówienie zostało zarejestrowane w systemie i oczekuje na akceptację przez obsługę, klient jest również proszony o pozostanie na stronie, gdzie będzie mógł obserwować. W poprzednim poście wyjaśniłem, że obsługa dostaje powiadomienie o utworzeniu nowego zamówienia i przystępuje do jego realizacji. Cały proces zmiany statusów zamówienia jest “jednoprzyciskowy” i polega wyłącznie na zmianie jego statusu. Za wyjątkiem pierwszej zmiany, która polega na akceptacji zamówienia i wybrania z popupa szacunkowego czasu na realizację zamówienia. Po jego zaakceptowaniu klient jest informowany o zmianie na stronie statusu, przed oczami zobaczy piękny timer i będzie informowany o dalszych zmianach.
I chociaż całość jest jeszcze tak naprawdę w trakcie, to najbardziej interesująca jest jedna rzecz. Ostatnio pisałem jak wysłać powiadomienie z klienta do Huba i z niego do wszystkich nasłuchujących klientów. Dziś zajmę się się odrobinę inną sytuacją, która będzie polegała na wysłaniu powiadomień tylko jednemu lub kilku odbiorcom.
W SignalR możemy użyć do tego celu kilku sposobów, zdecydowanie najbardziej odpowiadały moim potrzebom grupy, które można szybko dostosować do moich zamiarów. Zacznijmy od konfiguracji. Będziemy poruszać się od końca, od odbiorcy wiadomości, do jej nadawcy. Zacznijmy od dołączenia do grupy, podobnie jak poprzednio jest to JavaScript, w tym wypadku kod znajduje się w widoku, którego modelem jest int zawierający ID zamówienia, w przyszłości ze względów bezpieczeństwa mam zamiar podmienić ID na GUID.
1 2 3 4 5 6 7 8 9 |
$(function () { var orderHub = $.connection.ordersHub; $.connection.hub.start().done(function () { orderHub.server.joinGroup(@Model); }); orderHub.client.changeOrderStatus = function (status, minutes) { $("div.currentStatus").append("<p> Zamówienie zmieniło status, przybliżony czas realizacji to " + minutes + " minut"); }; }); |
Dosyć ważna jest trzecia linia, która odpowiada za dołączenie do grupy. Powinna być ona umieszczona w .done(), a co za tym idzie być wykonywana dopiero po wynegocjowaniu i ustanowieniu połączenia z Hubem. Jeśli już przy nim jesteśmy, to doszły do niego nowe metody, które wykorzystują grupy.
1 2 3 4 5 6 7 8 9 |
public void ChangeOrderStatus (string groupName, string status, int minutes = 0) { Clients.Group(groupName).changeOrderStatus(status, minutes); } public void JoinGroup(string groupName) { Groups.Add(Context.ConnectionId, groupName); } |
Jak łatwo się domyśleć metoda JoinGroup() dołącza klienta wywołującego metodę do grupy o podanej nazwie – w tym wypadku id zamówienia. Z kolei ChangeOrderStatus() odpowiada za zmiany statusu zamówienia. A wywoływany jest z poziomu panelu administracyjnego, podczas kliknięcia w przycisk zmiany statusu zamówienia.
1 2 3 4 5 6 7 8 9 |
$(function () { var orderHub = $.connection.ordersHub; $.connection.hub.start().done(function () { $(".acceptOrder").click(function () { var orderId = $(this).attr("id"); orderHub.server.changeOrderStatus(orderId, "Accepted", 60); }); }); }); |
Póki co jedynym parametrem jaki jest pobierany (z id buttona, które odpowiada ID obsługiwanego zamówienia) jest ID. Reszta nie jest gotowa i w tej chwili jest ustawiona na sztywno. Jednakże cel został osiągnięty i za pomocą zaledwie kilkunastu linijek kodu otrzymaliśmy efekt, który pozwala na powiadamianie klienta o statusie zamówienia na bieżąco, w czasie rzeczywistym i bez wysyłania mu kilku różnych emaili/smsów. Wystarczy sam link do strony śledzącej.