Lekce 6 - Obsluha formulářů v ASP.NET Core MVC
V předchozím kvízu, Kvíz - MVC, pohled, middleware, routování v ASP.NET Core MVC, jsme si ověřili nabyté zkušenosti z předchozích lekcí.
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
:

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:

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
Views/_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:

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 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 (ne Razor View - Empty). 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:

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:

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ář:

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.