6. diel - Obsluha formulárov v ASP.NET Core MVC
V predchádzajúcom kvíze, Kvíz - MVC, pohľad, middleware, routovanie v ASP.NET Core MVC, sme si overili nadobudnuté skúsenosti z predchádzajúcich lekcií.
V dnešnom ASP.NET Core tutoriále si vyskúšame techniku
napojenia modelu priamo na View
. Tejto technike sa hovorí
model binding a hodí sa najmä pri práci s formulármi.
Programovať budeme jednoduchú kalkulačku.
Založíme si nový projekt podľa šablóny ASP.NET Core Web App
(Model-View-Controller), ktorý pomenujeme MVCKalkulacka
:
Touto šablónou nám budú vygenerované jednotlivé
zložky pre MVC komponenty a nastavené východiskové
routy a konfigurácie, ktoré sme minule robili
ručne. Ďalej nám bude vygenerovaná aj zložka wwwroot/
pre
statický (nemenný) obsah webu. Tu budeme umiestňovať napríklad obrázky, CSS súbory alebo JavaScript
súbory. Visual Studio nám sem do zložky
lib/
taktiež automaticky pridalo populárne knižnice Bootstrap a jQuery. Minule sme túto šablónu
nevyužili, aby sme lepšie pochopili, ako ASP.NET Core a architektúra MVC
funguje.
Ako názov projektu nepoužívajte len
Kalkulacka
, pretože by kolidoval s názvom našej triedy, ktorú
si ďalej vytvoríme.
Bude nám vygenerovaný aj ukážkový projekt. Môžeme si ho skúsiť spustiť:
My tento projekt nebudeme potrebovať, a preto vyprázdnime všetok obsah
zložiek Models/
, Controllers/
a Views/
v
okne Solution Explorer. Ponecháme si však súbor
_ViewImports.cshtml
, inak by nám správne nefungovali tzv.
tag helpers (viď ďalej).
Pokiaľ by sme začínali s prázdnym projektom ako minule, museli by sme tento súbor pridať ručne.
Rovnako si ukážme, ako bude naša hotová kalkulačka vyzerať:
Model
Začnime opäť modelom, ktorým bude trieda Kalkulacka
. Tú si
vytvoríme v zložke Models/
.
Vlastnosti
Modelu pridáme niekoľko verejných vlastností, konkrétne dve
vstupné čísla, vybranú operáciu a
výsledok. Poslednou vlastnosťou bude zoznam
typu SelectListItem
, ktorý bude obsahovať možné operácie pre
pohľad. Ten z nich následne vyrenderuje HTML element
<select>
. Zoznam rovno naplníme v konštruktore:
public class Kalkulacka { public int PrvniCislo { get; set; } public int DruheCislo { get; set; } public double Vysledek { get; private set; } public string Operace { get; set; } public List<SelectListItem> MozneOperace { get; private set; } public Kalkulacka() { Operace = "+"; MozneOperace = new List<SelectListItem> { new SelectListItem { Text = "Sečti", Value = "+", Selected = true }, new SelectListItem { Text = "Odečti", Value = "-" }, new SelectListItem { Text = "Vynásob", Value = "*" }, new SelectListItem { Text = "Vyděl", Value = "/" } }; } }
Vlastnosť Text
triedy SelectListItem
je popis
možnosti, ktorú vidí používateľ. Value
je hodnota, ktorá sa
odosiela na server (nemala by obsahovať diakritiku). Môžeme nastaviť aj
vlastnosť Selected
, ktorá označuje či má byť položka pri
zobrazení stránky vybraná.
Nezabudneme na pridanie
using Microsoft.AspNetCore.Mvc.Rendering
pre typ
SelectListItem
.
Metóda VypocitejVysledek()
Zostáva len metóda s nejakou logikou, ktorá podľa zvolenej
Operace
a hodnôt v PrvniCislo
a
DruheCislo
vypočíta Vysledek
:
public void VypocitejVysledek() { Vysledek = Operace switch { "+" => PrvniCislo + DruheCislo, "-" => PrvniCislo - DruheCislo, "*" => PrvniCislo * DruheCislo, "/" => PrvniCislo / DruheCislo, _ => 0 }; }
Výsledok sa po zavolaní metódy uloží do vlastnosti
Vysledek
. Rovnako tak by sme ho mohli aj vrátiť, ako sme to
robili v minulom projekte s náhodným číslom. Pre naše ďalšie zámery s
bindingom to ale bude takto výhodnejšie.
Namiesto klasického switch
tu využívame jeho úspornejší
variant, ktorý máme k dispozícii od C# 9 a ktorý sa práve v tejto
situácii hodí, pretože nám značne zjednoduší kód.
Model máme hotový, pridajme si kontrolér.
Controller
Kontrolér budeme mať v našej aplikácii zase len jeden. Určite si spomíname, že kontrolér slúži na prepojenie modelu (logiky) a pohľadu (HTML šablóny).
Do zložky Controllers/
si pridáme nový MVC
Controller-Empty a pomenujeme ho HomeController
. Tento
kontrolér sa spustí pri vstupe na predvolenú stránku aplikácie, pretože je
naň v súbore Program.cs
nasmerovaná predvolená URL adresa.
Prejdime do jeho kódu a akciu Index()
upravme do nasledujúcej
podoby:
public IActionResult Index() { Kalkulacka kalkulacka = new Kalkulacka(); return View(kalkulacka); }
Pri vstupe na stránku sa zavolá akcia Index()
, to už vieme.
Vtedy vytvoríme novú inštanciu modelu, čo je stále rovnaké ako minule.
Novo však model odovzdáme pohľadu ako parameter.
Nezabudneme na pridanie using MVCKalkulacka.Models
pre Kalkulacka
.
View
Pre akciu Index()
vygenerujeme pohľad. To urobíme opäť
kliknutím pravým tlačidlom kamkoľvek do akcie, zvolením Add
View... a potom Razor View (nie Razor View - Empty). Ako
Template zvolíme Create a Model class nastavíme na
Kalkulacka. Nezabudneme odškrtnúť možnosť Use
a layout page, aby sme mali v pohľade zahrnutú aj základnú HTML
štruktúru:
Template nám umožňuje do pohľadu rovno predgenerovať nejaký kód, tejto technike sa hovorí scaffolding. Template Create vygeneruje pohľad napojený na zvolený model ak vlastnostiam tohto modelu vygeneruje formulár pre vytvorenie inštancie modelu. Keď aplikáciu teraz spustíme, vyzerá takto:
Vidíme, že Visual Studio vygenerovalo celkom štyri vstupy. Dva pre
čísla a po jednom pre výsledok a
operáciu. Operáciu však budeme chcieť zadávať pomocou
elementu <select>
a výsledok nebudeme vypisovať do
formulárového poľa, ale do HTML odseku <p>
.
Pohľad Index
Presunieme sa preto do súboru Index.cshtml
a zmeníme ho do
nasledujúcej podoby:
@model MVCKalkulacka.Models.Kalkulacka <!DOCTYPE html> <html lang="cs"> <head> <meta name="viewport" content="width=device-width" /> <title>Kalkulačka</title> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> </head> <body class="m-3"> <h1>Kalkulačka</h1> <div class="row"> <div class="col-md-4"> <form asp-action="Index"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="PrvniCislo"></label> <input asp-for="PrvniCislo" class="form-control" /> <span asp-validation-for="PrvniCislo" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="DruheCislo"></label> <input asp-for="DruheCislo" class="form-control" /> <span asp-validation-for="DruheCislo" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Operace"></label> @Html.DropDownListFor(model => model.Operace, new SelectList(Model.MozneOperace, "Value", "Text"), new { @class = "form-select" }) <span asp-validation-for="Operace" class="text-danger"></span> </div> <div class="form-group mt-3"> <input type="submit" value="Vypočítej" class="btn btn-primary" /> </div> <p class="h3 mt-3">@Model.Vysledek</p> </form> </div> </div> <script src="~/lib/jquery/dist/jquery.min.js"></script> @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } </body> </html>
Zmien sme oproti pôvodnej podobe šablóny až tak veľmi nevykonali. Na
úplnom začiatku šablóny vidíme nastavenie typu modelu
@model MVCKalkulacka.Models.Kalkulacka
, na ktorý je pohľad
nabindovaný (naviazaný). Ďalej sme v hlavičke stránky
<head>
nastavili titulok stránky a
nalinkovali knižnicu Bootstrap s
predpripravenými CSS triedami, ktoré využívame na štylovanie celej
stránky.
Všimnime si použitie tildy (~
) na získanie cesty
do zložky wwwroot/
, kde sa zložka s knižnicou Bootstrap nachádza.
Obsah stránky sme obalili do elementu <body>
, na ktorého
začiatok sme umiestnili nadpis. Nasleduje formulár, ktorý vygenerovalo Visual
Studio a ktorý sme iba upravili. Na konci formulára vypisujeme vlastnosť
Vysledek
modelu Kalkulacka
do HTML odstavca
<p>
, čím ho zobrazíme užívateľovi.
Tag helpers
Jednotlivé editačné polia pre vlastnosti modelu vkladáme týmto štýlom:
<div class="form-group"> <label asp-for="NazevVlastnosti"></label> <input asp-for="NazevVlastnosti" class="form-control" /> <span asp-validation-for="NazevVlastnosti" class="text-danger"></span> </div>
Atribúty asp-for
sú tzv. tag helpers, pomocou
ktorých dokáže ASP.NET Core vygenerovať pre našu vlastnosť vhodný
ovládací prvok. Napríklad pre dátum sa vloží
DatePicker
a podobne. Tento atribút zároveň zaisťuje prepojenie
popisku <label>
so zodpovedajúcim vstupom
<input>
.
Chybové hlášky
Atribút asp-validation-for
vloží priestor na výpis
chybovej hlášky v prípade, že používateľ pole zle
vyplní. To sa zistí z dátového typu vlastnosti alebo prípadne pomocou
špeciálnych validačných atribútov (o tých si ešte povieme ďalej v
kurze). Všetko teda funguje úplne automaticky. Drobnou nevýhodou je, že
danú vlastnosť odovzdávame helperu ako text. Visual Studio nám našťastie
správnosť kódu dokáže skontrolovať aj tak.
Atribút asp-validation-summary
na elemente
<div>
umiestnenom na začiatku formulára zaistí zobrazenie
zhrnutia všetkých chýb, ktoré pri spracovaní formulára
nastanú:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
Tento atribút môže nadobúdať jednu z troch hodnôt:
All
- vypíšu sa všetky chyby,ModelOnly
- vypíšu sa všetky chyby okrem tých spôsobených zlým vyplnením poľa,None
- nevypíšu sa žiadne chyby.
ModelOnly
, ktorá je vhodná v kombinácii
s atribútom asp-validation-for
. Chyby spôsobené nesprávnym
vyplnením poľa sa zobrazia priamo pri danom poli. Zvyšné chyby sa potom
zobrazia na začiatku formulára.
V rámci tag helpers máme k dispozícii aj niektoré špeciálne HTML elementy.
HTML helper
Môžeme vidieť, že kombinujeme tag helpers so starším systémom
vkladania ovládacích prvkov pomocou tzv. HTML helperu typu
IHtmlHelper
. Nie všetky ovládacie prvky sú totiž v súčasnosti
tag helpermi podporované, niekedy sa tomuto riešeniu preto nevyhneme. K
inštancii tohto helperu pristupujeme cez vlastnosť Html
(@Html
).
Týmto spôsobom napríklad pridávame pomocou metódy
DropDownListFor()
element <select>
na výber
operácie. Tejto metóde odovzdávame tri argumenty:
- názov vlastnosti, do ktorej sa má uložiť výsledok výberu,
- zoznam položiek výberu typu
SelectList
a - anonymný objekt s atribútmi a ich hodnotami, ktoré sa majú pridať vygenerovanému elementu.
SelectList
vytvárame z položiek uložených v našom
modeli vo vlastnosti MozneOperace
. V konštruktore zoznamu taktiež
musíme definovať, aká vlastnosť položky obsahuje hodnotu a aká popis danej
položky.
Preferujeme napájanie formulárových prvkov na vlastnosti
modelu pomocou tag helperov (napríklad asp-for
) ako pomocou
zavináčov. Predsa chceme, aby HTML šablóna vyzerala čo najviac ako HTML
kód
Akcie formulára
Vráťme sa ešte na chvíľu k samotnému formuláru, ktorému nastavujeme
atribút asp-action
. Opäť sa jedná o tag helper z ASP.NET Core,
ktorým hovoríme, na akú akciu sa má obsah formulára
odoslať pri jeho potvrdení (napr. kliknutím na tlačidlo typu
submit
). My chceme, aby sa odosielal na akciu Index()
z kontroléra HomeController
, preto tomuto atribútu nastavujeme
názov danej akcie Index()
.
V akom kontroléri sa má akcia hľadať, potom môžeme určiť atribútom
asp-controller
. Bez uvedenia tohto atribútu sa akcia hľadá v
kontroléri daného pohľadu. V našom prípade tento atribút teda uvádzať
nemusíme.
Skripty pre validáciu
Vždy je nutné overovať, či dáta, ktoré nám užívateľ posiela, sú v
poriadku a zodpovedajú tomu, čo očakávame. Je teda nutné dáta
validovať. Preto na úplnom konci elementu
<body>
pripájame skripty potrebné na správne fungovanie
automatickej validácie vstupov ešte vo webovom
prehliadači.
Tieto skripty sa nachádzajú v súbore
_ValidationScriptsPartial.cshtml
, ktorý nám bol vygenerovaný v
priečinku Views/Shared/
. Ide o tzv. čiastočný
pohľad (partial view), teda pohľad obsahujúci iba malú,
znovupoužiteľnú časť HTML kódu, ktorú môžeme vkladať do iných
pohľadov. Používame na to asynchrónnu
metódu RenderPartialAsync()
HTML helperu, ktoré akurát
odovzdávame názov požadovaného pohľadu.
Pre správne fungovanie vyžadujú validačné skripty ešte aj skripty
knižnice jQuery, ktoré máme v
projekte už predinštalované a ktoré načítame o riadok vyššie pomocou
elementu <script>
.
Pohľad _ViewImports
Aby nám tag helpers v projekte fungovali, je potrebné v ňom mať aj súbor
pomenovaný _ViewImports.cshtml
s nasledujúcim obsahom:
@using MVCKalkulacka @using MVCKalkulacka.Models @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Rovnako ako v C# súboroch, aj v .cshtml
súboroch pracujeme s
mennými priestormi, ktoré obsahujú nami používané triedy. Súbor
_ViewImports.cshtml
obsahuje príkazy using
na
importovanie menných priestorov, ktoré sa majú pripojiť ku každému
pohľadu.
Súbor _ViewImports.cshtml
už v projekte máme v
priečinku Views/
.
Spustenie aplikácie
Po spustení aplikácie uvidíme takýto formulár:
Po jeho odoslaní sa zatiaľ nič nestane. Pokračovať budeme zase až nabudúce.
V budúcej lekcii, Spracovanie dát a validácia v ASP.NET Core MVC , sa naučíme spracovávať dáta odoslané formulárom. Zmienime sa o fungovaní HTTP a nakoniec zavedieme validačné anotácie v modeloch.