Lekce 5 - Pohled, middleware a routování v ASP.NET Core MVC
V minulé lekci, První webová aplikace v ASP.NET Core MVC, jsme začali s tvorbou naší první webové aplikace v ASP.NET Core MVC, kterou je generátor náhodných čísel.
V dnešním ASP.NET Core tutoriálu si do naší první webové aplikace v ASP.NET Core MVC doplníme pohled, middleware a routování.
View
V naší aplikaci nám ještě chybí šablona (pohled), ve které výstup zobrazíme uživateli.
Pojmy šablona a pohled se budou v kurzu zaměňovat, bude tím myšlen vždy pohled.
View (pohled) nejjednodušeji přidáme přímo z příslušného kontroleru.
Klikneme pravým tlačítkem kamkoli do metody Index()
a zvolíme
Add View...:
V nově otevřeném okně vybereme Razor View - Empty a potvrdíme:
Pohled se bude jmenovat stejně jako metoda:
Po potvrzení vytvoření se nám vygeneruje HTML šablona s následujícím obsahem:
@* For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 *@ @{ }
Na začátku vidíme komentář zapsaný mezi zavináče s hvězdičkami a blok pro C# kód začínající zavináčem a ohraničený složenými závorkami. To je syntaxe tzv. Razor engine, který slouží pro vkládání C# kódu do HTML. Existuje ještě několik dalších renderovacích enginů, ale téměř se nepoužívají.
Již víme, že všechna logika by měla být obsažena v modelech. V pohledech budeme C# používat pouze k výpisu hotových dat, které jsme z modelů získali. Razor direktiv by v šablonách mělo být co možná nejméně.
Základní struktura
Aktuální obsah šablony smažeme a vytvoříme si validní strukturu HTML dokumentu:
<!DOCTYPE html> <html lang="cs"> <head> <meta charset="utf-8" /> <title>Online generátor náhodných čísel</title> </head> <body> </body> </html>
Jak můžeme vidět, zatím se jedná o klasické HTML. Pokud jsme tedy absolvovali základní kurz tvorby webových stránek, tak by nás zde nemělo nic překvapit. Stránce jsme nastavili:
- jazyk na češtinu,
- kódování
UTF-8
a - titulek.
U webů s více podstránkami nebývají šablony těchto podstránek přímo výsledné HTML stránky, ale pouze jejich části, které se vkládají do tzv. layoutu. Layoutem je označována část HTML kódu, která je pro všechny stránky našeho webu společná. Typicky tedy obsahuje pouze hlavičku, navigaci a patičku webu. V šabloně podstránky se pak nachází pouze to, co je součástí dané konkrétní podstránky. Řešení s layoutem si ještě ukážeme dále v kurzu.
Tělo stránky
Nyní již do šablony doplníme samotný obsah v těle
<body>
. Stránka bude zobrazovat pouze jeden nadpis a
odstavec s vygenerovaným náhodným číslem:
<body> <h1>Náhodné číslo</h1> <p style="font-size: 2em;">@ViewBag.Cislo</p> </body>
Náhodné číslo vypisujeme z kolekce ViewBag
, kam ho uložil
kontroler. Ten ho získal z modelu, který ho vygeneroval.
Základní Razor syntaxe
Ke kolekci ViewBag
přistupujeme přes Razor direktivu
@
. Pokaždé, když chceme v šabloně vykonat C# příkaz, který
má do šablony vložit nějaký obsah, tak před něj napíšeme zavináč
@
.
V případě, kdy potřebujeme vykonat:
- příkaz, který nic nevrací,
- příkaz přiřazení nebo
- po sobě více příkazů najednou,
tak daný kód umístíme do bloku, který začíná
zavináčem @
a je ohraničený složenými závorkami
{}
. Takto bychom například mohli vypsat druhou mocninu
vygenerovaného čísla s uložením výsledku do proměnné:
<body> <h1>Náhodné číslo</h1> <p style="font-size: 2em;"> @{ int mocnina = ViewBag.Cislo * ViewBag.Cislo; @mocnina } </p> </body>
V pohledech by se správně neměly takové výpočty vyskytovat. Výpočty se umisťují do v modelu a v pohledu přes kontroler se pouze předávají výsledky. Docílí se tak lepší přehlednosti našeho kódu, když bude většina logiky umístěna pouze v modelu.
Z bloku kódu můžeme vracet i HTML elementy. Následující ukázka vygeneruje stejný HTML kód jako ta předchozí:
<body> <h1>Náhodné číslo</h1> @{ int mocnina = ViewBag.Cislo * ViewBag.Cislo; <p style="font-size: 2em;"> @mocnina </p> } </body>
Tyto dvě ukázky berme opravdu jen jako ukázky. V naší aplikaci budeme pracovat s verzí vypisující pouze vygenerované náhodné číslo, ne jeho druhou mocninu.
URL adresa
Jistě víte, že každá webová stránka je na internetu identifikována svou unikátní URL adresou. Taková URL adresa se skládá především z:
- doménového jména a
- cesty.
Mějme například tuto adresu:
https://www.domena.cz/home/index
Část www.domena.cz
je zde doménovým jménem a část
/home/index
je pak cestou. Doménové jméno bývá pro jeden web
většinou neměnné. Cesta už se však pro každou stránku webu liší.
Právě cesta URL adresy totiž identifikuje konkrétní stránku daného webu.
Cesta se skládá z libovolného množství segmentů
oddělených lomítkem /
.
Výše zvolená adresa nebyla zvolena náhodně. Když se podíváme na její
cestu /home/index
, tak ta odpovídá struktuře naší aplikace. V
naší aplikaci máme kontroler HomeController
, který má akci
Index()
. Uvedená cesta splňuje obecně používanou
konvenci řešící směrování (mapování) cesty URL adresy
na akce kontrolerů v ASP.NET aplikacích. Prvním segmentem je vždy název
kontroleru, druhým je název akce daného kontroleru a zbylé segmenty pak
slouží jako případné parametry.
Middleware, zpracování požadavků a routování
Kdybychom naši aplikaci nyní spustili (např. klávesovou zkratkou
Ctrl + F5), zobrazila by se pouze hláška "Hello World!"
a náš kontroler by se nespustil vůbec. Jelikož jsme při vytváření
projektu zvolili prázdnou šablonu, musíme HomeController
sami
nasměrovat, aby se spustil jako výchozí.
Právě tomuto mechanismu směrování URL adres na kontrolery nebo jiné části aplikace se říká routování.
Routování se nastavuje v souboru Program.cs
, jehož obsah
nyní vypadá asi následovně:
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
Do tohoto souboru budeme psát registrace služeb a
většinu konfigurací aplikace, jejíž sestavení zajišťuje
instance třídy WebApplicationBuilder
s metodou
Build()
. Jak si můžeme všimnout, hláška "Hello World!" by se
po spuštění aplikace zobrazila proto, že je zde ve výchozím stavu pomocí
metody MapGet()
nastaveno směrování cesty /
na
navrácení právě tohoto řetězce.
Do souboru Program.cs
můžeme do sestavené aplikace dále
psát tzv. middleware. Middleware si v ASP.NET Core můžeme
představit jako sérii filtrů, přes které postupně putuje požadavek od
uživatele na server, než se najde ten vhodný, který jej zpracuje. Mají
podobu rozšiřujících metod na instanci sestavené aplikace
(některým z vás pravděpodobně připomenou návrhový vzor Chain
of responsibility, protože se řetězí).
Každý middleware v řetězci má pouze omezenou a specifickou
roli ve zpracování požadavku - např. první může plnit jen funkci loggeru,
další middleware bude hledat nějakou cookie nebo autorizační token. A pokud
nenajde co hledá, vrátí chybovou hlášku nebo uživatele přesměruje.
Např. middleware UseFileServer()
nám umožní jako odpověď
vrátit statický obsah (skripty v Javascriptu, obrázky, CSS soubory atd.)
našeho projektu a podobně.
V .NET 5.0 a starších verzích je kód souboru
Program.cs
vyčleněn do metod ConfigureServices()
a
Configure()
v souboru Startup.cs
. V metodě
ConfigureServices()
se registrují služby a v metodě
Configure()
se konfiguruje middleware na již sestavené
aplikaci.
Routování na kontroler
Budeme tedy chtít, aby se uživatel hned po spuštění aplikace nasměroval
na kontroler HomeController
a jeho akci Index()
.
Zároveň budeme chtít, aby všechny cesty splňovaly výše uvedenou konvenci,
tedy aby měly vzor /nazev_kontroleru/nazev_akce
. K tomu využijeme
middleware MapControllerRoute()
, který se stará o napojení
cesty URL adresy na akce kontroleru:
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapControllerRoute("default", "{controller=Home}/{action=Index}"); app.Run();
Metodě MapControllerRoute()
nejprve předáváme
název vytvářeného vzoru cesty default
a poté
samotný vzor. Ve vzoru zde máme uvedené dva segmenty:
{controller=Home}
a{action=Index}
.
Obalením segmentů do složených závorek {}
a použitím
klíčových slov controller
a action
říkáme, že
při zpracování URL adresy se první segment bude považovat za název
kontroleru a druhý za název akce. Za rovnítkem uvádíme výchozí hodnotu,
která se má použít v případě, že uživatel daný segment neuvede.
Například ve chvíli, kdy uživatel uvede pouze cestu /home
, tak
se tato cesta automaticky doplní na /home/index
a nasměruje se na
akci Index()
kontroleru HomeController
.
Těmto typům middleware, které požadavek směrují na kontrolery, se říká routy.
Registrace služeb
Při spuštění projektu by se tedy měla zavolat akce Index()
kontroleru HomeController
. Když jej nyní ovšem spustíme, čeká
nás nepříjemně vypadající výjimka o chybějících službách:
ASP.NET Core framework se skládá z velkého množství granulárních služeb a komponent, které jsou pro fungování MVC potřebné. Aby vše mohlo správně fungovat tak, jak očekáváme, musíme tyto služby do naší aplikace nejdříve zaregistrovat (k čemuž nás nabádá i text výjimky).
Přesuneme se proto zpět do souboru Program.cs
a ještě před
sestavením aplikace zaregistrujeme potřebné služby pomocí metody
AddControllersWithViews()
:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); // Tento řádek jsme přidali var app = builder.Build(); app.MapControllerRoute("default", "{controller=Home}/{action=Index}"); app.Run();
Druhý pokus
Projekt spustíme a uvidíme tentokrát správný výsledek:
Port aplikace v URL adrese budete mít pravděpodobně jiný než já.
Na naši stránku se dostaneme i po uvedení celé URL adresy:
Nebo jen části:
Zopakování
Ještě si naposledy zopakujme jak celá aplikace funguje.
Nejdříve je požadavek uživatele zpracován našimi
middlewary a přeroutován (posunut)
kontroleru HomeController
. Poté je spuštěna jeho akce
Index()
. Ta se zeptá modelu na data a data uloží do kolekce
ViewBag
. Následně je vyrenderován pohled, který pomocí Razor
syntaxe na určitá místa v šabloně vypisuje data z kolekce
Viewbag
. Hotová stránka je odeslána uživateli.
V následujícím kvízu, Kvíz - MVC, pohled, middleware, routování v ASP.NET Core MVC, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 262x (7.32 kB)
Aplikace je včetně zdrojových kódů v jazyce C#