7. diel - Spracovanie dát a validácia v ASP.NET Core MVC
V minulej lekcii, Obsluha formulárov v ASP.NET Core MVC, sme načali spracovanie formulárov a napojenie modelu na pohľad.
V dnešnej lekcii ASP.NET Core dokončíme našu jednoduchú kalkulačku. Naučíme sa odosielať dáta z formulára späť na server a zaistíme, aby tieto dáta boli validné. Okrem toho spomenieme aj fungovanie HTTP.
Budeme pokračovať s projektom z lekcie Obsluha formulárov v ASP.NET Core MVC.
Odoslanie formulára
Pri odoslaní formulára našej kalkulačky sa zatiaľ nič nestane. Je to z
toho dôvodu, že formulár odošle dáta na tú istú
stránku. Požiadavka teda zachytí akcie Index() v
kontroléri HomeController:
public IActionResult Index() { Calculator calculator = new Calculator(); return View(calculator); }
Aj po odoslaní formulára sa teda vytvorí nová inštancia kalkulačky, ktorá má nulový výsledok a tá sa nastaví pohľadu. Preto je výsledok stále nula. Situácii odoslania formulára na stránku, ktorá ho má spracovať, sa niekedy hovorí postback. My by sme práve na túto situáciu potrebovali reagovať iným spôsobom, než že opäť vypíšeme stránku určenú pre situáciu, keď používateľ ešte nič neodoslal.
Do kontroléra HomeController napíšeme ďalšiu akciu
Index(), tentoraz s parametrom a anotovaným atribútom
[HttpPost]:
[HttpPost] public IActionResult Index(Calculator calculator) { if (ModelState.IsValid) { calculator.CalculateResult(); } return View(calculator); }
V metóde nám príde parametrom inštancia kalkulačky tak, ako bola
vytvorená z hodnôt v odoslanom formulári. Ak je model
validný, čo zistíme pomocou vlastnosti
ModelState, zavoláme metódu na výpočet.
Nakoniec vrátime pohľad, ktorému odovzdáme daný model so
zadanými hodnotami a výsledkom.
Metóda je označená atribútom [HttpPost]. Tým zjednodušene
hovoríme, že si prajeme, aby bola spustená iba v prípade, že sa
odoslal formulár. ASP.NET vždy spúšťa to preťaženie
akcie, ktoré sa najviac hodí na danú situáciu. Odoslanie formulára
teda už nespadne do prvej akcie Index(), ale až do tej novej.
Aplikáciu môžeme vyskúšať. Už sa nám bude zobrazovať výsledok operácie:

Vyplnené zostanú aj ostatné polia, pretože sa hodnota
načíta z modelu, ktorý ju má nastavenú z metódy anotovanej atribútom
[HttpPost].
Ako ale ASP.NET presne vie, že má pri odosielaní formulára vykonávať
práve preťaženie anotované atribútom [HttpPost]? A čo tento
atribút v skutočnosti znamená? Aby sme dokázali na tieto otázky odpovedať,
tak si najskôr musíme aspoň zjednodušene vysvetliť fungovanie HTTP.
HTTP
Hyper Text Transfer Protocol, skrátene HTTP, je jedným z najrozšírenejších protokolov používaných na komunikáciu po internete.
Komunikácia pomocou tohto protokolu je založená na dopytoch (požiadavkách) a odpovediach na ne. Klient posiela dopyty na webový server a ten mu naspäť zasiela odpovede s dátami. V našom prípade je klientom webový prehliadač, ktorý žiada webový server napr. o zaslanie HTML stránky. Server po prijatí takého dopytu vygeneruje požadovanú stránku a odošle ju späť v rámci odpovede klientovi:

Dnes je už štandardom zabezpečená verzia tohto protokolu, označovaná HTTPS.
Štruktúra HTTP dopytu a odpovede
Dopyty klienta musia obsahovať predovšetkým:
- typ dopytu, teda tzv. HTTP metódu, a
- adresu dopytu nesúcu informáciu o tom, aké dáta a odkiaľ sú žiadané.
Ďalej dopyt môže (ale nemusí) ešte mať aj:
- hlavičky obsahujúce dodatočné informácie, napr. o klientovi, a
- telo s dátami, ktoré chceme poslať s dotazom na server.
Odpoveď servera sa potom skladá najmä zo:
- stavu požiadavky, teda jeho úspešnosti,
- hlavičiek obsahujúcich dodatočné informácie o prenášaných dátach, napr. o type dát, a
- samotných dát, ktorými môže byť akýkoľvek textový dokument. Väčšinou sa jedná o dokumenty vo formáte HTML, XML, JSON alebo napríklad CSV.
HTTP metódy
HTTP metóda dopytu označuje spôsob, akým má server na danú otázku reagovať. Základnými HTTP metódami sú metódy:
GET(prečítať),POST(vytvoriť),PUT(upraviť),DELETE(zmazať).
Zaslaním dopytu s HTTP metódou GET napr. hovoríme, že od
servera žiadame nejaké dáta. S touto metódou sú teda posielané všetky
požiadavky webového prehliadača na zaslanie webovej stránky. Pri
potvrdení formulára a posielaní jeho hodnôt sa potom
najčastejšie používa metóda POST. Dáta sa odosielajú vo
vnútri HTTP dopytu na server. Hoci sa to nemusí vždy striktne dodržiavať,
metóda POST slúži hlavne na vkladanie nových
dát.
Atribúty pre HTTP metódy
V ASP.NET Core MVC aplikáciách sa jednotlivé dopyty smerujú pomocou mechanizmu routovania na jednotlivé akcie kontroléra. V tomto mechanizme hrajú rolu práve aj HTTP metódy. Pri každej akcii môžeme určiť, akú HTTP metódu musí dopyt mať, aby mohol danú akciu vyvolať. Používame na to špeciálne atribúty metód. Pre vyššie uvedené HTTP metódy sa jedná o atribúty:
[HttpGet]– metódaGET,[HttpPost]– metódaPOST,[HttpPut]– metódaPUT,[HttpDelete]– metódaDELETE.
Anotáciou nášho nového preťaženia akcie
Index() atribútom [HttpPost] teda hovoríme, že sa
má vykonať vo chvíli, keď je zaslaná otázka na danú stránku s metódou
POST. V našom prípade sa jedná o potvrdenie formulára.
Pri vyžiadaní našej stránky prehliadačom sa pošle dopyt s metódou
GET. Pre túto metódu však nemáme v kontroléri žiadne
preťaženie akcie Index(). Dopyt sa preto nasmeruje na našu
neanotované preťaženie akcie Index().
Vo chvíli, keď ASP.NET nedokáže nájsť preťaženie akcie anotovanej vhodným atribútom, tak volí preťaženie bez atribútu, ak existuje.
Dáta v URL adrese
Pri metóde POST sa dáta odovzdávajú v tele dopytu, pri
metóde GET to však takto nefunguje. V prípade použitia metódy
GET môžeme využiť odovzdávanie dát priamo v URL adrese.
Slúžia na to tzv. parametre URL adresy. Ide o položky typu
kľúč-hodnota, ktoré píšeme na koniec adresy za znak otáznika
? a oddeľujeme ich znakom &. Hodnotou takýchto
položiek môže byť akýkoľvek reťazec.
Urobme si jednoduchý príklad použitia parametra odovzdaného metódou
GET. Keby sme napr. chceli v URL adrese uviesť venovanie, pre koho
je kalkulačka vytvorená, vyzerala by URL adresa takto:
Prípadne rozpísaná ako:
Váš port bude samozrejme opäť iný.
Načítanie parametrov v akcii
Index()
Aby sme takúto hodnotu načítali, presunieme sa do prvej akcie
Index(), ktorej pridáme parameter. Hodnoty
parametrov URL adresy máme v akcii k dispozícii cez rovnomenné parametre
metódy:
public IActionResult Index(string name) { Calculator calculator = new Calculator(); ViewBag.Name = name; return View(calculator); }
Parameter odovzdávame pohľadu pomocou kolekcie ViewBag.
Pohľad Index
Parameter vypíšeme v pohľade Index v nadpise
<h1>:
<h1> Calculator @if (ViewBag.Name != null) { <text> for @ViewBag.Name</text> } </h1>
Ak je parameter name zadaný (nie je null),
vypíšeme do nadpisu ešte "for" a obsah tohto parametra.
Razor direktíva @if
Prvýkrát tu používame špeciálnu Razor direktívu @if,
ktorá funguje obdobne ako klasický if z C#. Ak uvedená podmienka
platí, vloží sa do pohľadu obsah nasledujúceho bloku, v opačnom prípade
sa vloží obsah bloku else, ak je uvedený.
Ak v konštrukcii @if vypisujeme obyčajný text,
mal by byť obalený v elemente <text>.
Výsledok:

Parameter by sme rovnako dobre mohli namiesto pohľadu odovzdať modelu. V kalkulačke ma nenapadá žiadne využitie, v aplikácii na generovanie náhodných čísel by parameter mohol udávať koľko čísel si prajeme vygenerovať.
Už teda vieme odovzdávať dáta skriptu na serveri, a to buď cez
parametre URL adresy alebo v tele HTTP dopytu
s metódou POST. Metódu POST používajú najmä
formuláre. Parametre URL adresy využijeme ak chceme použiť
inú HTTP metódu ako POST.
Popisy polí formulára
Popisy pri poliach formulára obsahujú text s názvom
vlastnosti, ku ktorej sa viažu. Názvy ako FirstNumber
však nie sú pre používateľov príliš vábne. Preto vlastnosti v triede
Calculator anotujeme atribútom [Display] s
ľudskejším popisom:
public class Calculator { [Display(Name = "1. number")] public int FirstNumber { get; set; } [Display(Name = "2. number")] public int SecondNumber { get; set; } public double Result { get; private set; } [Display(Name = "Operation")] public string Operation { get; set; } public List<SelectListItem> AvailableOperations { get; private set; } //... }
Atribút [Display] sa nachádza v mennom priestore
System.ComponentModel.DataAnnotations, nezabudne si ho teda
pridať.
Výsledok:

Validácia
Poslednou témou, ktorú si na našej kalkulačke vyskúšame, bude validácia. Vždy je totiž nutné overovať, či dáta, ktoré nám užívateľ posiela, sú v poriadku a zodpovedajú tomu, čo očakávame. Ak v našej kalkulačke nezadáme číslo v správnom formáte alebo zadáme napríklad text, potom by sa nám nemalo podariť formulár odoslať.
Základné validácie sa v ASP.NET Core generujú automaticky podľa dátového typu danej vlastnosti modelu a sú tak na strane klienta, ako aj na strane servera. Ak zadáme neplatný vstup, zachytí ho ešte pred odoslaním na server validátor v JavaScripte. Požiadavka sa teda vôbec neodošle. Pre istotu musí byť vždy tá istá validácia aj na serveri, pretože klient si môže napr. JavaScript vypnúť.
Atribúty pre validáciu
Ďalšie požiadavky na validáciu pridávame vo forme atribútov. Pár si ich uvedieme.
Atribút [Required]
Atribút [Required] nám umožňuje určiť, či je zadanie
poľa nutné. Všetky nenullovateľné hodnotové typy (napr. int,
decimal, DateTime...) sú považované za
[Required] automaticky. Ak však chceme definovať vlastnú
chybovú hlášku, ktorá sa má užívateľovi zobraziť pri nevyplnení poľa,
tak daný atribút musíme použiť. Anotujme ním vlastnosti
FirstNumber, SecondNumber a
Operation:
public class Calculator { [Display(Name = "1. number")] [Required(ErrorMessage = "Enter the first number.")] public int FirstNumber { get; set; } [Display(Name = "2. number")] [Required(ErrorMessage = "Enter the second number.")] public int SecondNumber { get; set; } public double Result { get; private set; } [Display(Name = "Operation")] [Required(ErrorMessage = "Select an operation.")] public string Operation { get; set; } //... }
Chybovú hlášku definujeme nastavením vlastnosti ErrorMessage
atribútu.
Atribút [Range]
Pri číslach môžeme ďalej validovať ich rozsah pomocou atribútu
[Range]. Pridajme si ho napríklad k vlastnostiam
FirstNumber a SecondNumber:
public class Calculator { [Display(Name = "1. number")] [Required(ErrorMessage = "Enter the first number.")] [Range(1, 100, ErrorMessage = "Enter a number from 1 to 100.")] public int FirstNumber { get; set; } [Display(Name = "2. number")] [Required(ErrorMessage = "Enter the second number.")] [Range(1, 100, ErrorMessage = "Enter a number from 1 to 100.")] public int SecondNumber { get; set; } //... }
Môžeme si skúsiť, že sa hlášky skutočne vypíšu. Skúsme treba
zadať do poľa pre prvé číslo písmeno e, v druhom poli nechať
nulu a formulár potvrdiť tlačidlom Calculate:

Vidíme, že hlášky sa automaticky vypisujú do elementov s atribútmi
asp-validation-for, ktoré sú umiestnené pod poľami
formulára.
Model kalkulačky je teraz plný atribútov a je teda prispôsobený hlavne pre View, preto sa týmto modelom často hovorí ViewModel.
Atribút [StringLength]
Atribútom [StringLength] môžeme validovať dĺžku
reťazcov:
[StringLength(5)]
Atribút
[RegularExpression]
Reťazce môžeme tiež validovať pomocou regulárnych
výrazov, a to atribútom [RegularExpression]:
[RegularExpression("\\d+", ErrorMessage = "Invalid code")]
Zmena chybových hlášok
Určite sme si všimli, že hlášku informujúcu o chybne zadanom čísle
sme nikde nezadávali. Ide totiž o hlášku vygenerovanú validačnými
skriptmi a skriptmi knižnice jQuery,
ktoré načítavame v súbore Index.cshtml na konci tela elementu
<body>:
<body class="m-3"> <!-- The rest of the content... --> <script src="~/lib/jquery/dist/jquery.min.js"></script> @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } </body>
Tieto hlášky našťastie môžeme meniť rozšírením JavaScript objektu jQuery.validator.messages,
ktorý je vytváraný validačnými skriptami. Urobíme to pomocou funkcie
jQuery.extend().
Keďže sa jedná o použitie knižnice jQuery a JavaScriptu, ktorý nie je témou tohto kurzu, tak zvyšný obsah lekcie berte skôr len ako taký bonus pre záujemcov.
Pridajme si pod importované skripty nový element
<script> a nastavme v ňom vlastné chybové hlášky
informujúce o chybne zadanom čísle alebo číslici:
<body class="m-3"> <!-- The rest of the content... --> <script src="~/lib/jquery/dist/jquery.min.js"></script> @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } <script> jQuery.extend(jQuery.validator.messages, { number: "Enter a number in the correct form.", digits: "Enter numbers only." }); </script> </body>
Definíciu objektu jQuery.validator.messages a
všetky jeho nastaviteľné hlášky nájdeme v súbore
jquery-validate.js v priečinku
wwwroot/lib/jquery-validation/dist/. Hlášky však nie je vhodné
meniť priamo v tomto súbore, pretože napr. pri aktualizácii knižnice s
validačnými skriptmi by sa nám zmeny prepísali.
Keď aplikáciu teraz spustíme a vyskúšame si validáciu, tak uvidíme naše hlášky:

To by bolo v našej kalkulačke už všetko.
V nasledujúcom kvíze, Kvíz - Formuláre, dáta, validácia v ASP.NET Core MVC, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 10x (1.54 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#
