Po poprzednim wpisie, gdzie opisywałem bardzo ogólnikowo Blazora, pora na przyjrzenie się jego kolejnym elementom. W tym wpisie dowiesz się jak stworzyć projekt aplikacji WebAssembly. Następnie jakie elementy występują w wzorcowym projekcie. Na koniec opiszę komponenty – jak je tworzyć i używać. Jeśli chcesz przeczytać o koncepcji i umiejscowieniu Blazor’a w ekosystemie .NET’a to zapraszam do poprzedniego wpisu! >LINK<

Nowy projekt

Na start potrzebujemy:

  • Visual Studio 2019 (zalecam aktualizację do najnowszej wersji)
  • .NET 5.0 (zalecany, może być 3.1 CORE)

Zacznijmy od założenia projektu. W tym celu:

  • Uruchamiamy nasze IDE – VS2019
  • Klikamy Create a new Project
  • Wybieramy Blazor App (możemy wspomóc się wyszukiwarką)
  • Nadajemy nazwę – ja użyję nazwy bloga, czyli Power-Dev
  • Klikamy Create

Następnie:

  • Wybieramy Blazor WebAssembly App oraz:
    • w prawym górnym rogu wybieramy: .NET 5.0
    • authentication: No Authentication
    • advanced: Configure for HTTPS oraz ASP.NET Hosted
    • NIE zaznaczamy Progressive Web Application (dodamy je w kolejnych wpisach)
  • Klikamy Create
blazor webassembly

Gdy już stworzyliśmy nasz projekt, to pora go uruchomić! Wybieramy *.Server i wciskamy F5 (bądź ) .

blazor webassembly

Jeśli zastanawiasz się czemu akurat *.Server, skoro chcemy uruchomić aplikację, która ma działać po stronie klienta przeglądarkowego, to już tłumaczę. Wcześniej wspomniany projekt będzie hostował naszą aplikację Blazor’ową (jej pliki) oraz służył jako API.

Równie dobrze moglibyśmy odpalić *.Client jednak, odpalając *.Server mamy to samo + API.

Po uruchomieniu się aplikacji, naszym oczom ukaże się strona z kultowym Hello World! Z lewej strony znajduję się menu nawigacji, z trzema elementami menu:

  1. Home – strona główna na której znajduje się przywitanie. Pod nim znajduje się zachęta do wzięcia udziału w ankiecie na temat Blazor’a
  2. Counter – tutaj znajdziemy element interaktywny. Jest nim przycisk, po kliknięciu którego zwiększona zostanie liczba wyświetlana powyżej niego. Jeśli byśmy uruchomili narzędzie developerskie przeglądarki (w Chrome F12) i przeszli do zakładki network, to zauważymy że wcześniej wspomniana akcja nie wiąże się z żadnym zapytaniem do API. Co oznacza że wykonuje się po stronie przeglądarki!
  3. Fetch data – przykład gdzie pobierane są dane z API a później wizualizowane
blazor webassembly

Struktura projektu

W przypadku gdy stworzymy aplikację tak jak wcześniej opisywałem, w solucji zobaczymy trzy projekty:

  • Server
  • Client
  • Shared

Shared

Omawianie zacznę od ostatniego, z racji że jest klasycznym projektem współdzielonym, gdzie znajduję się kod używany przez wiele aplikacji. Będziemy tutaj umieszczać najczęściej modele danych. Jednak szczególnie interesujący jest tutaj plik .csproj w którym znajduje się:

<ItemGroup>
    <SupportedPlatform Include="browser" />
</ItemGroup> 

Konstrukcja ta pozwala naszemu IDE ostrzegać nas przed użyciem bibliotek/metod, które nie są obsługiwane w oknie przeglądarki. Aby ten mechanizm zadziałał autor kodu (który chcemy użyć) musi oznaczyć swoją metodę atrybutem UnsupportedOSPlatform.

[UnsupportedOSPlatform("browser")]
private static string GetLoggingDirectory()
{
    // ...
}

Zważywszy na planowane rozszerzenie Blazor’a na wiele platform, to trzeba uznać, że wprowadzenie takiego elementu jest dobrym ruchem.

Server

Jako kolejnemu przyjrzyjmy się projektowi Server. W gruncie rzeczy jest to zwykłe WebApi. Mimo to są dwa pliki w których możemy znaleźć coś nowego.

Pierwszym z nich jest Startup.cs, w którym konfigurujemy następujące opcje:

  • debugowanie WebAssembly (gdy aplikacja jest uruchomiona w trybie developerskim)
  • dostarczanie naszej aplikacji pod głównym adresem strony
  • przekierowanie do pliku index.html w razie problemów z routingiem
blazor

Drugim plikiem jest lauchSetting.json a w nim:

blazor

Ustawienie to pozwala IDE wykryć że uruchamiamy aplikacje WebAssembly. Wskazuję również adres do trybu debugowania w przeglądarce, który wykorzystywany zostanie przez VS. Dzięki temu możemy śledzić wykonywanie kodu z okna IDE.

Client

Pora na omówienie najważniejszego dla nas projektu:

  • Program.cs
    • tutaj wszystko się zaczyna. Tworzony jest WebHost (podobnie jak to miało miejsce w MVC/WebApi). A czym jest WebHost? W skrócie, jest to „silnik”, który obsługuje m.in logowanie zdarzeń, zarządzanie konfiguracją oraz kieruje cyklem życia aplikacji. Więcej przeczytasz >TUTAJ<
    • wskazywany jest element DOM, w którym wyrenderuje się główny komponent (element ten znajdziemy w index.html)
    • dodawane są elementy kontenera DI, na przykład serwisy
    • na koniec uruchamiany jest w/w WebHost
  • wwwroot – folder na statyczny kontent naszej aplikacji, taki jak:
    • grafiki
    • skrypty JavaScript
    • pliki HTML oraz CSS – znajdziemy tam m.in. index.html. Służy on jako bazowy plik widoku. Dołączany w nim jest plik blazor.webassembly.js, który pobiera środowisko uruchomieniowe .NET oraz zależności aplikacji
  • App.razor – tutaj znajduje się Router, czyli wbudowany komponent, który odpowiedzialny jest za nawigację i wyświetlanie odpowiedniej zawartości
  • Pages – folder, w którym według proponowanej konwencji, znajdować się będą komponenty do których możemy się bezpośrednio nawigować
  • Shared – folder, w którym znajdziemy:
    • MainLayount.razor – jak sama nazwa wskazuje opisuje on domyślne rozmieszczenie elementów na stronie. Więcej o Layout’ach przeczytasz w dedykowanym wpisie
    • NavMenu.razor jest komponentem, który pełni funkcję menu. W wpisie o autoryzacji opiszę jak uzależnić jego wygląd od posiadanych uprawnień
  • _Imports.razor – przechowuje namespace’y, które będą dołączane w każdym komponencie

Komponenty

Było sporo teorii, teraz jeszcze tylko kilka słów o komponentach samych w sobie i ruszamy z kodem! Z dokumentacji możemy wyczytać, że są one samowystarczającymi fragmentami interfejsu użytkownika, strony lub formularza. Zawierają one znaczniki HTML oraz logikę potrzebną do przetwarzania interakcji z użytkownikiem.

Komponent może być zagnieżdżany, wielokrotnie używany oraz współdzielony pomiędzy projektami. Warto pamiętać że można je współdzielić miedzy wersją WASM a Server.

Aby dodać komponent, należy w wybranym miejscu w solucji kliknąć prawym przyciskiem myszy Add -> Razor Component…

blazor component

Jednak zanim to zrobimy, stwórzmy pod-folder w Pages i nazwijmy go Athletes. A w nim dodajmy komponent o nazwie AthletesOverview. Kluczowym elementem tutaj jest aby nazwa zaczynała się z wielkiej litery – jest to wymagane. Niektórzy są zwolennikami konwencji, gdzie na koniec nazwy dopisujemy 'Component' np. AthletesOverviewComponent. Decyzję co będziesz używać zostawiam już Tobie.

blazor webassembly

Po dodaniu, plik otworzy się automatycznie. Zmieńmy w nim treść nagłówka h3 na „Nasi Sportowcy”.  Następnie dodajmy dyrektywę @page oraz routing np. @page „/Athletes”,  ważne żeby adres zaczynał się od znaczku „/” (slash).

Ostatnią (na ten moment!) czynnością do wykonania, jest dodanie do komponentu odpowiedzialnego za menu hiperłącza do naszej strony. Zatem w folderze Shared szukamy pliku NavMenu.razor.

blazor webassembly

Dodajemy w nim kolejny element <li> (List Item). Tag ten oznacza kolejną pozycję w liście – w tym przypadku nieuporządkowanej <ul> (Unordered List). Zmieniamy href na wartość wpisaną poprzednio przy @page.  Drugą podkreśloną wartością jest tekst, który będzie się wyświetlał w menu.

Warto zmienić też ikonę przy naszym linku, dlatego wpiszmy w właściwości class oi-beaker zamiast oi-list-rich. Więcej darmowych ikon znajdziemy np. >TUTAJ<

Uruchamiamy aplikację i naszym oczom ukazuję się znany już widok, jednak w menu znajduję się czwarta pozycja! Klikamy na nią i… cel został osiągnięty. Wodotrysków nie ma (jeszcze!), ale bez wątpienia na LinkedIn możemy już wpisać Blazor Regular Developer 😝.

blazor webassembly

Code behind

Domyślnie proponowane nam jest pisanie widoku (Razor/HTML) oraz logiki UI w jednym pliku. Dla wielu osób jest to nieprzejrzyste, zwłaszcza gdy nasze komponenty się rozrosną. Jednak łatwo możemy podzielić nasz kod na dwa pliki (tak jak w MVC, Razor Pages). W Visual Studio mamy nawet możliwość wyświetlania tych plików jako jeden (zagnieżdżone).

Aby podzielić komponent na część UI i logiki należy:

  1. W tym samym folderze dodać klasę, nadając jej taką samą nazwę jak posiada nasz komponent + końcówkę .cs np. AthletesOverview.razor.cs
  2. W pliku .cs dodać słowo kluczowe partial przed class np.
    public partial class AthletesOverview
  3. Włączyć zagnieżdżanie plików w Solution Explorer
blazor webassembly

Takie podejście ma wiele zalet, jednak w uogólnieniu sprowadza się do dwóch.

Pierwszą z nich jest rozdzielenie logiki aplikacji od widoków, co bezpośrednio przekłada się na ułatwione wyszukiwanie fragmentów kodu odpowiedzialnych za konkretną funkcjonalność. Wiele osób wyznaję zasadę „jedna klasa – jeden ekran”, którą ciężko by było utrzymać mając całość komponentu w jednym pliku.

Kluczową zaletą jest wsparcie IntelliSense, które przy rozbiciu komponentu działa o wiele lepiej. Chyba nie musze nikogo przekonywać że dopisywanie using’ów (przez IntelliSense) jest wystarczającym plusem by używać „code-behind”.

To teraz dokonajmy paru zmian:

  • Dodajmy plik code-behind
  • Stwórzmy zmienną przechowującą tekst wyświetlany w naszym komponencie (może być prywatna)
  • Umieśćmy ją w pliku .razor w nagłówku h3
blazor webassembly
Efekt rozbicia komponentu na dwa pliki

Podsumowanie

Wiemy już:

  • jak założyć projekt aplikacji Blazor WebAssembly
  • z jakich elementów składa się wzorcowy projekt
  • jak wygląda struktura projektu i gdzie umiejscawiać konkretne typy elementów aplikacji
  • jak podzielić komponent na pliki odpowiedzialne za logikę oraz wygląd

Ponadto mamy już podstawową wiedzę o komponentach, która będzie fundamentem pod kolejne wpisy! A jeżeli nie chcesz ich przegapić to zapraszam na newsletter! Zapisy pod tym LINKiem!

Do zobaczenia w kolejnym wpisie!