IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 6 - Obsluha formulářů v ASP.NET Core MVC

V dnešním ASP.NET Core tutoriálu si vyzkoušíme techniku napojení modelu přímo na View. Této technice se říká model binding a hodí se zejména při práci s formuláři. Programovat budeme jednoduchou kalkulačku.

Založíme si nový projekt podle šablony ASP.NET Core Web App (Model-View-Controller), který pojmenujeme MVCKalkulacka:

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

Touto šablonou nám budou vygenerovány jednotlivé složky pro MVC komponenty a nastaveny výchozí routy a konfigurace, které jsme minule dělali ručně. Dále nám bude vygenerována i složka wwwroot/ pro statický (neměnný) obsah webu. Zde budeme umisťovat například obrázky, CSS soubory nebo JavaScript soubory. Visual Studio nám sem do složky lib/ také automaticky přidalo populární knihovny Bootstrap a jQuery. Minule jsme tuto šablonu nevyužili, abychom lépe pochopili, jak ASP.NET Core a architektura MVC funguje.

Jako název projektu nepoužívejte jen Kalkulacka, jelikož by kolidoval s názvem naší třídy, kterou si dále vytvoříme.

Bude nám vygenerován i ukázkový projekt. Můžeme si jej zkusit spustit:

Výchozí projekt v ASP.NET Core MVC - Základy ASP.NET Core MVC

My tento projekt nebudeme potřebovat, a proto vyprázdníme veškerý obsah složek Models/, Controllers/ a Views/ v okně Solution Explorer. Ponecháme si ovšem soubor _ViewImports.cshtml, jinak by nám správně nefungovaly tzv. tag helpers (viz dále).

Pokud bychom začínali s prázdným projektem jako minule, museli bychom tento soubor přidat ručně.

Rovnou si ukažme, jak bude naše hotová kalkulačka vypadat:

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

Model

Začněme opět modelem, kterým bude třída Kalkulacka. Tu si vytvoříme ve složce Models/.

Vlastnosti

Modelu přidáme několik veřejných vlastností, konkrétně dvě vstupní čísla, vybranou operaci a výsledek. Poslední vlastností bude seznam typu SelectListItem, který bude obsahovat možné operace pro pohled. Ten z nich následně vyrenderuje HTML element <select>. Seznam rovnou naplníme v konstruktoru:

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 = "/" }
        };
    }

}

Vlastnost Text třídy SelectListItem je popisek možnosti, který vidí uživatel. Value je hodnota, která se odesílá na server (neměla by obsahovat diakritiku). Můžeme nastavit i vlastnost Selected, která označuje zda má být položka při zobrazení stránky vybraná.

Nezapomeneme na přidání using Microsoft.AspNetCore.Mvc.Rendering pro typ SelectListItem.

Metoda VypocitejVysledek()

Zbývá jen metoda s nějakou logikou, která podle zvolené Operace a hodnot v PrvniCislo a DruheCislo vypočítá Vysledek:

public void VypocitejVysledek()
{
    Vysledek = Operace switch
    {
        "+" => PrvniCislo + DruheCislo,
        "-" => PrvniCislo - DruheCislo,
        "*" => PrvniCislo * DruheCislo,
        "/" => PrvniCislo / DruheCislo,
        _ => 0
    };
}

Výsledek se po zavolání metody uloží do vlastnosti Vysledek. Stejně tak bychom ho mohli i vrátit, jako jsme to dělali v minulém projektu s náhodným číslem. Pro naše další záměry s bindingem to ale bude takto výhodnější.

Namísto klasického switch zde využíváme jeho úspornější variantu, kterou máme k dispozici od C# 9 a která se zrovna v této situaci hodí, protože nám značně zjednoduší kód.

Model máme hotový, přidejme si kontroler.

Controller

Kontroler budeme mít v naší aplikaci zase jen jeden. Určitě si vzpomínáme, že kontroler slouží k propojení modelu (logiky) a pohledu (HTML šablony).

Do složky Controllers/ si přidáme nový MVC Controller - Empty a pojmenujeme ho HomeController. Tento kontroler se spustí při vstupu na výchozí stránku aplikace, jelikož je na něj v souboru Program.cs nasměrována výchozí URL adresa. Přejděme do jeho kódu a akci Index() upravme do následující podoby:

public IActionResult Index()
{
    Kalkulacka kalkulacka = new Kalkulacka();
    return View(kalkulacka);
}

Při vstupu na stránku se zavolá akce Index(), to již víme. Tehdy vytvoříme novou instanci modelu, což je stále stejné, jako minule. Nově však model předáme pohledu jako parametr.

Nezapomeneme na přidání using MVCKalkulacka.Models pro Kalkulacka.

View

Pro akci Index() vygenerujeme pohled. To uděláme opět kliknutím pravým tlačítkem kamkoli do akce, zvolením Add View... a poté Razor View. Jako Template zvolíme Create a Model class nastavíme na Kalkulacka. Nezapomeneme odškrtnout možnost Use a layout page, abychom měli v pohledu zahrnutu i základní HTML strukturu:

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

Template nám umožňuje do pohledu rovnou předgenerovat nějaký kód, této technice se říká scaffolding. Template Create vygeneruje pohled napojený na zvolený model a k vlastnostem tohoto modelu vygeneruje formulář pro vytvoření instance modelu. Když aplikaci nyní spustíme, vypadá takto:

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

Vidíme, že Visual Studio vygenerovalo celkem čtyři vstupy. Dva pro čísla a po jednom pro výsledek a operaci. Operaci však budeme chtít zadávat pomocí elementu <select> a výsledek nebudeme vypisovat do formulářového pole, ale do HTML odstavce <p>.

Pohled Index

Přesuneme se proto do souboru Index.cshtml a změníme ho do následující 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>

Změn jsme oproti původní podobě šablony až tak moc neprovedli. Na úplném začátku šablony vidíme nastavení typu modelu @model MVCKalkulacka.Models.Kalkulacka, na který je pohled nabindovaný (navázaný). Dále jsme v hlavičce stránky <head> nastavili titulek stránky a nalinkovali knihovnu Bootstrap s předpřipravenými CSS třídami, které využíváme ke stylování celé stránky.

Všimněme si použití tildy (~) pro získání cesty do složky wwwroot/, kde se složka s knihovnou Bootstrap nalézá.

Obsah stránky jsme obalili do elementu <body>, na jehož začátek jsme umístili nadpis. Následuje formulář, který vygenerovalo Visual Studio a který jsme pouze upravili. Na konci formuláře vypisujeme vlastnost Vysledek modelu Kalkulacka do HTML odstavce <p>, čímž ho zobrazíme uživateli.

Tag helpers

Jednotlivá editační pole pro vlastnosti modelu vkládáme tímto stylem:

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

Atributy asp-for jsou tzv. tag helpers, pomocí kterých dokáže ASP.NET Core vygenerovat pro naši vlastnost vhodný ovládací prvek. Například pro datum se vloží DatePicker a podobně. Tento atribut zároveň zajišťuje propojení popisku <label> s odpovídajícím vstupem <input>.

Chybové hlášky

Atribut asp-validation-for vloží prostor pro výpis chybové hlášky v případě, že uživatel pole špatně vyplní. To se zjistí z datového typu vlastnosti nebo případně pomocí speciálních validačních atributů (o těch si ještě povíme dále v kurzu). Vše tedy funguje zcela automaticky. Drobnou nevýhodou je, že danou vlastnost předáváme helperu jako text. Visual Studio nám naštěstí správnost kódu dokáže zkontrolovat i tak.

Atribut asp-validation-summary na elementu <div> umístěném na začátku formuláře zajistí zobrazení shrnutí všech chyb, které při zpracování formuláře nastanou:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>

Tento atribut může nabývat jedné ze tří hodnot:

  • All - vypíší se všechny chyby,
  • ModelOnly - vypíší se všechny chyby kromě těch způsobených špatným vyplněním pole,
  • None - nevypíší se žádné chyby.

My používáme hodnotu ModelOnly, která je vhodná v kombinaci s atributem asp-validation-for. Chyby způsobené špatným vyplněním pole se zobrazí přímo u daného pole. Zbylé chyby se pak zobrazí na začátku formuláře.

V rámci tag helpers máme k dispozici i některé speciální HTML elementy.

HTML helper

Můžeme vidět, že kombinujeme tag helpers se starším systémem vkládání ovládacích prvků pomocí tzv. HTML helperu typu IHtmlHelper. Ne všechny ovládací prvky jsou totiž v současnosti tag helpery podporovány, někdy se tomuto řešení proto nevyhneme. K instanci tohoto helperu přistupujeme přes vlastnost Html (@Html).

Tímto způsobem například přidáváme pomocí metody DropDownListFor() element <select> pro výběr operace. Této metodě předáváme tři argumenty:

  • název vlastnosti, do které se má uložit výsledek výběru,
  • seznam položek výběru typu SelectList a
  • anonymní objekt s atributy a jejich hodnotami, které se mají přidat vygenerovanému elementu.

Seznam SelectList vytváříme z položek uložených v našem modelu ve vlastnosti MozneOperace. V konstruktoru seznamu taktéž musíme definovat, jaká vlastnost položky obsahuje hodnotu a jaká popisek dané položky.

Preferujeme napojování formulářových prvků na vlastnosti modelu pomocí tag helperů (třeba asp-for) než pomocí zavináčů. Přeci chceme, aby HTML šablona vypadala co nejvíce jako HTML kód :)

Akce formuláře

Vraťme se ještě na chvíli k samotnému formuláři, kterému nastavujeme atribut asp-action. Opět se jedná o tag helper z ASP.NET Core, kterým říkáme, na jakou akci se má obsah formuláře odeslat při jeho potvrzení (např. kliknutím na tlačítko typu submit). My chceme, aby se odesílal na akci Index() z kontroleru HomeController, proto tomuto atributu nastavujeme název dané akce Index().

V jakém kontroleru se má akce hledat, pak můžeme určit atributem asp-controller. Bez uvedení tohoto atributu se akce hledá v kontroleru daného pohledu. V našem případě tento atribut tedy uvádět nemusíme.

Skripty pro validaci

Vždy je nutné ověřovat, jestli data, která nám uživatel posílá, jsou v pořádku a odpovídají tomu, co očekáváme. Je tedy nutné data validovat. Proto na úplném konci elementu <body> připojujeme skripty potřebné pro správné fungování automatické validace vstupů ještě ve webovém prohlížeči.

Tyto skripty se nacházejí v souboru _ValidationScriptsPartial.cshtml, který nám byl vygenerovaný ve složce Views/Shared/. Jedná se o tzv. částečný pohled (partial view), tedy pohled obsahující pouze malou, znovupoužitelnou část HTML kódu, kterou můžeme vkládat do jiných pohledů. Používáme k tomu asynchronní metodu RenderPartialAsync() HTML helperu, které akorát předáváme název požadovaného pohledu.

Pro správné fungování vyžadují validační skripty ještě i skripty knihovny jQuery, které máme v projektu již předinstalované a které načítáme o řádek výše pomocí elementu <script>.

Pohled _ViewImports

Aby nám tag helpers v projektu fungovaly, je zapotřebí v něm mít i soubor pojmenovaný _ViewImports.cshtml s následujícím obsahem:

@using MVCKalkulacka
@using MVCKalkulacka.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Stejně jako v C# souborech, i v .cshtml souborech pracujeme se jmennými prostory, které obsahují námi používané třídy. Soubor _ViewImports.cshtml obsahuje příkazy using pro importování jmenných prostorů, které se mají připojit ke každému pohledu.

Soubor _ViewImports.cshtml již v projektu máme ve složce Views/.

Spuštění aplikace

Po spuštění aplikace uvidíme takovýto formulář:

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

Po jeho odeslání se zatím nic nestane. Pokračovat budeme zase až příště.

V příští lekci, Zpracování dat a validace v ASP.NET Core MVC, se naučíme zpracovávat data odeslaná formulářem. Zmíníme se o fungování HTTP a nakonec zavedeme validační anotace v modelech.


 

Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.

Předchozí článek
Kvíz - MVC, pohled, middleware, routování v ASP.NET Core MVC
Všechny články v sekci
Základy ASP.NET Core MVC
Přeskočit článek
(nedoporučujeme)
Zpracování dat a validace v ASP.NET Core MVC
Článek pro vás napsal Martin Petrovaj
Avatar
Uživatelské hodnocení:
321 hlasů
Autor je lenivý vymýšľať nejaký slušný podpis. Venuje sa ale prevažne C#.
Aktivity