F# Bolero - A cóż to takiego? - remoting
Posty z tej serii:
- F# Bolero - A cóż to takiego? - wprowadzenie
- F# Bolero - A cóż to takiego? - HTML templates
- F# Bolero - A cóż to takiego? - view components
- F# Bolero - A cóż to takiego? - routing
- F# Bolero - A cóż to takiego? - routing - page models
- F# Bolero - A cóż to takiego? - remoting
Aplikacja webowa składa się (w dużym uproszczeniu) z dwóch części:
- Widoków
- Danych, prezentowanych na widokach
Dane dla widoków możemy dostarczyć co najmniej na trzy sposoby:
- Wołamy zewnętrzne API bezpośrednio z aplikacji
- Tworzymy własne API, które dla aplikacji będzie punktem wejścia do wołania innych API
- Mix dwóch powyższych
Tworząc własne API dla aplikacji pisanej w Bolero, możemy skorzystać z mechanizmu Remoting, który w mojej subiektywnej opinii posiada trzy bardzo fajne właściwości:
- Szczegóły komunikacji między klientem a serwerem ukryte są pod warstwą abstrakcji
- Ten sam sposób używania, niezależnie od tego, czy pobieramy, czy wysyłamy dane
- Dwa wynikowe stany - udało się lub nie
W szczegółach, dane serilizowane są do formatu JSON oraz wymieniane przez protokół HTTP(s) z użyciem metody POST.
Zobaczmy, w jaki sposób możemy zaimplementować najprostsze API z jedną metodą, która zwraca tekst, a także, w jaki sposób możemy wywołać zaimplementowaną metodę.
Bolero Template umożliwia wygenerowanie kodu, gdzie serwer oraz klient skonfigurowani są w modelu hosted. My zrealizujemy scenariusz, w którym klient oraz serwer hostowani są niezależnie od siebie.
Cały kod znajdziesz na GitHub’e.
Zacznijmy od utworzenia trzech projektów:
-
kontrakty pomiędzy klientem, a serwerem - dll
dotnet new classlib -n Remoting.Contracts -lang f#
-
host serwera - ASP.NET Web API
dotnet new webapi -n Remoting.Server -lang f#
-
host klienta - Bolero minimal
dotnet new bolero-app -n Remoting.Client --minimal=true --server=false
Następnie, w projekcie Remoting.Contracts:
- dodajemy paczkę Bolero
dotnet add package Bolero
-
usuwamy plik
Library.fs
-
dodajemy plik
SimpleService.fs
z deklaracją API
Record SimpleService
zawiera pole GetHello
, które reprezentuje metodę API. Wynikiem wywołania GetHello
będzie zwrócenie przykładowego napisu. SimpleService
dziedziczy po interfejsie IRemoteService
z przestrzeni nazw Bolero.Remoting
. Member this.BasePath
wskazuje ścieżkę API. W ten sposób tworzymy deklarację, którą rozpozna Bolero.
Do projektu Remoting.Server:
- dodajemy paczkę Bolero.Server
dotnet add package Bolero.Server
- dodajemy referencję do projektu Remoting.Contracts:
dotnet add reference ../Remoting.Contracts
- dodajemy plik
SimpleServiceHandler.fs
z implementacją API
Klasa SimpleServiceHandler
dziedziczy po klasie RemoteHandler
z przestrzeni nazw Bolero.Remoting.Server
. Pod Handler
podstawiamy definicję metody API. Bolero umożliwia skorzystanie z dwóch zależności, dla których dostarcza implementacje: IRemoteContext
oraz IWebHostEnvironment
. W przykładzie pierwszą z nich wykorzystujemy, aby do odpowiedzi HTTP(s) dodać nagłówek Access-Control-Allow-Origin
.
- w pliku
Startup.fs
konfigurujemy ASP.NET Web API włączając Bolero Remoting oraz definiując CORS
Remoting włączamy poprzez wywołanie metod:
- services.AddControllers()
- app.UseRemoting()
CORS definiujemy poprzez wywołanie metod:
- services..AddCors()
- app.UseCors(…)
W konfiguracji hosted CORS nie jest potrzebny, ponieważ zarówno serwer, jak i klient uruchamiane są z tej samej domeny.
Na koniec, w projekcie Remoting.Client:
- dodajemy referencję do projektu Remoting.Contracts:
dotnet add reference ../../../Remoting.Contracts
- w pliku
Startup.fs
, włączamy Bolero Remoting , podając bazowe URI pod którym dostępne jest API
- w pliku
main.fs
, realizujemy aplikację, które zawoła API za pomocą Elmish Commands:
Definiujemy model
Ustawiamy początkowe wartości modelu
Nowością w stosunku do przykładów z poprzednich artykułów tej serii jest to, że wraz z wartościami modelu podajemy jaki Command ma się wykonać. W momencie inicjalizowania początkowych wartości nie wykonujemy żadnej akcji, oznaczając to przez Cmd.none
Definiujemy Messages
- GetHello - zawołanie API
- ShowHello - wykonanie działania, w przypadku, gdy API zwróci sukces
- ShowError - wykonanie działania, w przypadku, gdy API zwróci błąd
Definiujemy funkcję update
Oprócz standardowych parametrów message
oraz model
, funkcja przyjmuje parametr simpleService
. Parametr jest typem SimpleService
z projektu Remoting.Contracts
. Po nadejściu Message’a GetHello
wołamy API, za pomocą Command’a Cmd.OfAsync.either
. W przypadku prawidłowego zakończenia wywołania zostanie zgłoszony Message ShowHello
wpp. zostanie zgłoszony Message ShowError
. Przy sukcesie wypełniamy model zwróconym rezultatem wpp. opisem błędu.
Definiujemy funkcję view
Widok zawiera dwa elementy:
- przycisk z akcją
on.Click
, która wysyła MessageGetHello
- pole
text
, które wyświetla zawartość modelu
Na koniec zmieniamy inicjalizowanie głównego komponentu z mkSimple
na mkProgram
W ten sposób wstrzykujemy klienta API do funkcji update oraz dostajemy możliwość używania Elmish Commands.
Koniec Serii
Tak, oto dotarliśmy do końca serii, która pokazuje podstawowe możliwości Bolero. Dzięki przedstawionym mechanizmom możemy tworzyć rozwiązania webowe w podejściu SPA, pisząc kod w języku F#.
Bolero posiada o wiele więcej możliwości. Jest to jednak temat na osobną serię artykułów.
Jeśli chodzi o mnie, to zostaję przy frameworku. Pamiętam, jak pierwszy raz przeczytałem o jego koncepcjach i doznałem tego fajnego efektu “aha…ciekawe…”. Teraz kiedy znam Bolero trochę lepiej, nic się nie zmieniło :)
Kolejnym etapem rozwoju jest wymyślenie tematu na aplikację oraz jej realizacja. Efektami prac podzielę się na blogu, którego w dalszej perspektywie będę chciał przepisać właśnie w Bolero.
=