Dataczwartek, 13 sierpnia 2026 Czas18:10:20
← Aplikacje webowe

Lekcja 28. Blazor — interaktywny interfejs webowy w C#, bez JavaScriptu

Trudny / egzaminacyjny

Po 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

  1. Dodaj do licznika drugi przycisk "Zmniejsz" oraz etykietę informującą "Wartość jest ujemna!" widoczną (przez @if) wyłącznie, gdy licznik spadnie poniżej zera.

  2. Zbuduj komponent "Stoper" z przyciskami Start/Stop/Reset, korzystający z System.Threading.Timer albo PeriodicTimer do aktualizowania wyświetlanego czasu co sekundę (pamiętając, że aktualizacja stanu spoza normalnego cyklu zdarzeń Blazor wymaga wywołania InvokeAsync(StateHasChanged), żeby komponent odświeżył widok).

  3. 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.