Lekcja 28. Blazor — interaktywny interfejs webowy w C#, bez JavaScriptu
Trudny / egzaminacyjnyPo co się tego uczymy?
Ten i kolejne 4 tematy to materiał DODATKOWY, wykraczający poza wymagania egzaminu zawodowego INF.04.7 — oficjalna podstawa programowa (INF.04.7.2) i informator CKE o egzaminie zawodowym wymieniają jako wymagane frameworki: ASP.NET Core, Django, Angular, React.js, Node.js — Blazora tam NIE MA. Ten blok jest przeznaczony dla osób, które opanowały już WSZYSTKIE poprzednie, wymagane lekcje tego działu (1-18) i chcą poznać nowocześniejsze, w pełni firmowane przez Microsoft podejście do budowy interaktywnych aplikacji webowych w C#, bez konieczności uczenia się JavaScriptu/TypeScriptu. Razor Pages i MVC (lekcje 3-8) renderują gotowy HTML na serwerze — każda interakcja użytkownika (kliknięcie, wysłanie formularza) to NOWE żądanie HTTP i przeładowanie fragmentu strony. Nowoczesne aplikacje webowe (jak popularny framework Angular) często działają inaczej — jako interaktywne komponenty aktualizujące się natychmiast, bez przeładowania strony. Blazor to WŁASNA odpowiedź Microsoftu na ten sam problem — pozwala pisać dokładnie taki interaktywny interfejs, ale w C#, w Visual Studio 2026, bez uczenia się drugiego języka programowania (JavaScript/TypeScript) i osobnego zestawu narzędzi (Node.js, npm).
Teoria
Dlaczego Blazor, a nie Angular/React? Frameworki takie jak Angular czy React świetnie radzą sobie z budowaniem interaktywnych interfejsów, ale wymagają nauki JavaScriptu/TypeScriptu, osobnego środowiska (Node.js, npm, Angular CLI) i innego edytora przyzwyczajeń (choć technicznie da się je otworzyć w Visual Studio). Blazor daje DOKŁADNIE TĘ SAMĄ możliwość budowania komponentowego, interaktywnego interfejsu, ale w JĘZYKU C#, którego uczysz się od początku tego kursu (konsola, WPF, MAUI) — to trzeci (obok Razor Pages i MVC) sposób budowania interfejsu w ASP.NET Core, tym razem w pełni interaktywny, bez przeładowywania strony przy każdej akcji.
Dwa modele wykonania — Blazor Server i Blazor WebAssembly:
| Model | Gdzie wykonuje się kod C#? | Zalety | Wady |
|---|---|---|---|
| Blazor Server | na SERWERZE — przeglądarka utrzymuje stałe połączenie (SignalR/WebSocket), wysyła zdarzenia (kliknięcia), odbiera instrukcje aktualizacji ekranu | szybki start, mały rozmiar pobierania, pełny, bezpośredni dostęp do bazy danych bez oddzielnego API | wymaga STAŁEGO połączenia z serwerem; niewielkie opóźnienie przy każdej interakcji |
| Blazor WebAssembly (WASM) | W PRZEGLĄDARCE — cały skompilowany kod .NET pobierany jest na start i działa lokalnie, jak prawdziwe SPA (podobnie do Angulara) | działa bez stałego połączenia z serwerem po pobraniu; natychmiastowa reakcja UI | większy plik pobierania na starcie; dostęp do bazy danych wymaga OSOBNEGO Web API (lekcja 20) |
Ten kurs zaczyna od Blazor Server — prostszy model mentalny na start (mniej ruchomych części do zrozumienia naraz), ale WSZYSTKIE poznane tu komponenty i składnia .razor są niemal 1:1 przenoszalne do Blazor WebAssembly, gdybyś chciał później zbudować pełne SPA działające offline w przeglądarce.
Nowy, ujednolicony szablon "Blazor Web App" (Visual Studio 2026, .NET 8+) pozwala wybrać tryb interaktywności (None/Server/WebAssembly/Auto) osobno dla całej aplikacji ALBO per-strona/komponent przez dyrektywę @rendermode — to znaczy, że TA SAMA aplikacja może mieć część stron statycznych (szybkich, jak zwykłe Razor Pages) i część w pełni interaktywnych (Blazor), płynnie ze sobą współpracujących.
Anatomia komponentu Blazor (plik .razor). Jeden plik .razor łączy znaczniki HTML/Razor (widok) z blokiem @code { ... } zawierającym pola, właściwości i metody C# — to pojedynczy plik zamiast pary .cshtml/.cshtml.cs z Razor Pages (choć duże komponenty MOGĄ być podzielone na dwa pliki: Licznik.razor + Licznik.razor.cs, analogicznie do XAML+code-behind z WPF/MAUI). Kluczowe elementy: @page "/adres" (jeśli komponent ma być samodzielną, routowalną stroną), @rendermode InteractiveServer (włącza interaktywność), @onclick="MetodaCSharp" (podpięcie zdarzenia — bezpośredni odpowiednik Clicked="Metoda" z XAML w MAUI).
Schemat
Trzy sposoby budowania UI w ASP.NET Core:
Razor Pages (lekcje 3-7) MVC (lekcja 8) Blazor (ta lekcja)
GET/POST -> pełne Kontroler -> Widok Komponent .razor
przeładowanie strony -> pełne przeładowanie -> aktualizacja BEZ
przeładowania strony
Blazor Server:
Przeglądarka Serwer
│ klik <button @onclick="..."> │
│──────── zdarzenie przez SignalR ───────►│
│ │ wykonanie metody C# w @code
│ │ (może odczytać/zapisać bazę wprost)
│◄─── instrukcja aktualizacji DOM ─────────│
│ (tylko RÓŻNICA, nie cała strona) │
Blazor WebAssembly:
Przeglądarka pobiera CAŁY skompilowany kod .NET (runtime .NET w WASM)
│
▼
Kod C# wykonuje się LOKALNIE w przeglądarce, bez serwera
(dostęp do bazy danych: TYLKO przez osobne Web API, jak w lekcji 20)
Przykład z życia
Panel administracyjny pokazujący na żywo listę zamówień, która aktualizuje się natychmiast po dodaniu nowego zamówienia (bez odświeżania strony przez pracownika), albo interaktywny kalkulator przeliczający wynik w miarę wpisywania danych — to typowe zastosowania Blazora, dokładnie ten sam rodzaj "żywej", reagującej natychmiast aplikacji, jaki dotychczas kojarzyłeś z Angularem czy React, tylko teraz osiągalny w C#.
Components/Pages/Licznik.razor
<!-- Components/Pages/Licznik.razor -->
@page "/licznik"
@rendermode InteractiveServer
<h1>Licznik kliknięć</h1>
<p role="status">Aktualna wartość: @liczba</p>
<button class="btn btn-primary" @onclick="Zwieksz">Kliknij mnie</button>
<button @onclick="Zeruj">Zeruj</button>
blok @code + Program.cs + App.razor
// Components/Pages/Licznik.razor - blok @code (ten sam plik, poniżej znaczników)
@code {
private int liczba = ;
private void Zwieksz()
{
liczba++;
}
private void Zeruj()
{
liczba = ;
}
}
// ---------------------------------------------------------------------
// Program.cs - rejestracja Blazor (fragment)
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
// ---------------------------------------------------------------------
// Components/App.razor - główny plik hosta (uproszczony)
// <!DOCTYPE html>
// <html>
// <head><base href="/" /></head>
// <body>
// <Routes />
// <script src="_framework/blazor.web.js"></script>
// </body>
// </html>
Komentarz i wyjaśnienie kodu
Zwróć uwagę, że KAŻDE kliknięcie przycisku NATYCHMIAST aktualizuje wartość @liczba na ekranie — BEZ przeładowania strony i BEZ ręcznego pisania kodu odświeżającego widok (jak Label.Text = ... w WPF/MAUI). Blazor SAM śledzi, że pole liczba użyte w znaczniku @liczba się zmieniło, i automatycznie aktualizuje TYLKO ten fragment DOM w przeglądarce — to mechanizm bardzo podobny do INotifyPropertyChanged z lekcji o CollectionView w dziale MAUI, tylko wbudowany i automatyczny, bez pisania własnego kodu powiadamiania.
@rendermode InteractiveServer jest KLUCZOWY — bez niego komponent renderuje się TYLKO RAZ, statycznie (jak zwykła strona HTML), a przyciski w ogóle nie zadziałają, bo brakuje połączenia SignalR umożliwiającego przesyłanie zdarzeń do serwera.
app.MapRazorComponents<App>().AddInteractiveServerRenderMode() w Program.cs to rejestracja analogiczna do app.MapRazorPages()/app.MapControllers() z poprzednich lekcji — włącza mechanizm routingu i renderowania komponentów Blazor w Twojej aplikacji.
Ćwiczenie samodzielne
Utwórz nowy projekt szablonem "Blazor Web App" w Visual Studio 2026 (tryb interaktywności: Server), przeanalizuj domyślnie wygenerowany komponent Counter.razor (bardzo podobny do przykładu w tej lekcji), a następnie dodaj własny, analogiczny komponent z licznikiem i przyciskiem zerowania.
Zadania do pracy własnej
Dodaj do licznika drugi przycisk "Zmniejsz" oraz etykietę informującą "Wartość jest ujemna!" widoczną (przez
@if) wyłącznie, gdy licznik spadnie poniżej zera.Zbuduj komponent "Stoper" z przyciskami Start/Stop/Reset, korzystający z
System.Threading.TimeralboPeriodicTimerdo aktualizowania wyświetlanego czasu co sekundę (pamiętając, że aktualizacja stanu spoza normalnego cyklu zdarzeń Blazor wymaga wywołaniaInvokeAsync(StateHasChanged), żeby komponent odświeżył widok).Zbuduj komponent "Lista zadań" z polem tekstowym i przyciskiem "Dodaj" — nowe zadania powinny natychmiast pojawiać się na liście POD polem (przechowywane w
List<string>w bloku@code), z możliwością oznaczenia zadania jako wykonane (checkbox) i usunięcia pojedynczej pozycji — wszystko BEZ przeładowania strony, korzystając wyłącznie z mechanizmów Blazor poznanych w tej lekcji.
Typowe błędy
Zapomnienie o @rendermode InteractiveServer — najczęstsza pułapka na start; bez tej dyrektywy komponent renderuje się statycznie, przyciski wyglądają, ale nie reagują na kliknięcia.
Mylenie Blazor Server z Blazor WebAssembly co do tego, GDZIE faktycznie wykonuje się kod — w Blazor Server baza danych i pliki są dostępne bezpośrednio (kod działa na serwerze), a w Blazor WebAssembly analogiczny bezpośredni dostęp jest NIEMOŻLIWY (kod działa w przeglądarce użytkownika) i wymaga komunikacji przez Web API.
Traktowanie Blazor jako "zamiennika 1:1" dla Razor Pages/MVC bez zrozumienia różnicy w modelu wykonania — Blazor to INNY paradygmat (komponenty, stan trzymany w pamięci przez cały czas trwania sesji użytkownika), nie tylko inna składnia tego samego mechanizmu żądanie-odpowiedź.
Nawiązanie do egzaminu zawodowego
Uwaga: Blazor NIE jest wymieniony w INF.04.7.2 (oficjalna lista to ASP.NET Core, Django, Angular, React.js, Node.js) — ten blok lekcji jest materiałem DODATKOWYM, poza wymaganiami egzaminu zawodowego. Wiedza o architekturze komponentowej (parametry, zdarzenia, cykl życia) przenosi się jednak wprost na Angular/React, gdybyś zdecydował się nauczyć też jednego z nich pod kątem egzaminu. Kolejne lekcje rozwijają komponenty Blazor o parametry, zdarzenia niestandardowe, formularze z walidacją i routing.