IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

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:

Založenie nového ASP.NET MVC projektu - Základy ASP.NET Core MVC - Základy ASP.NET Core MVC

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ť:

Predvolený projekt v ASP.NET Core MVC - Základy ASP.NET Core MVC - Základy ASP.NET Core MVC

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ť:

Kalkulačka v ASP.NET Core MVC - Základy ASP.NET Core MVC - Základy ASP.NET Core MVC

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:

Scaffolding v ASP.NET Core MVC - Základy ASP.NET Core MVC - Základy ASP.NET Core MVC

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:

Vygenerovaná kalkulačka v ASP.NET Core MVC - Základy ASP.NET Core MVC - Základy ASP.NET Core MVC

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.
My používame hodnotu 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.
Zoznam 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:

MVC kalkulačka v ASP.NET Core - Základy ASP.NET Core MVC - Základy ASP.NET Core MVC

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.


 

Predchádzajúci článok
Kvíz - MVC, pohľad, middleware, routovanie v ASP.NET Core MVC
Všetky články v sekcii
Základy ASP.NET Core MVC
Preskočiť článok
(neodporúčame)
Spracovanie dát a validácia v ASP.NET Core MVC
Článok pre vás napísal Martin Petrovaj
Avatar
Užívateľské hodnotenie:
2 hlasov
Autor je lenivý vymýšľať nejaký slušný podpis. Venuje sa ale prevažne C#.
Aktivity