5. De weergave en het bijbehorende sjabloon
5.1. Introduction
Laten we terugkeren naar de architectuur van een ASP.NET MVC-toepassing:
![]() |
In het vorige hoofdstuk hebben we onderzocht hoe ASP.NET MVC de informatie van de aanvraag [1] aan een actie [2a] presenteerde in de vorm van een sjabloon dat validatiebeperkingen kon bevatten. Dit model werd als invoer aan de actie doorgegeven en we noemden het het actiemodel. We richten ons nu op het meest voorkomende resultaat van een actie, het type [ViewResult], dat overeenkomt met een weergave V [3], vergezeld van het bijbehorende model M [2c]. Dit model wordt het V-weergavemodel genoemd, niet te verwarren met het actiemodel dat we zojuist hebben besproken. Het ene is de invoer van de actie, het andere is de uitvoer.
Laten we beginnen met het aanmaken van een nieuw project [Exemple-03] [1], nog steeds binnen dezelfde oplossing, van het basistype ASP.NET MVC:
![]() |
Laten we een controller aanmaken met de naam [First] [2]. De gegenereerde code voor deze controller is als volgt:
using System.Web.Mvc;
namespace Exemple_03.Controllers
{
public class FirstController : Controller
{
public ActionResult Index()
{
return View();
}
}
}
- regels 7-10: er is een actie [Index] aangemaakt. Het type van het resultaat van de methode [Index] is dat van de klasse [ActionResult], waarvan de meeste mogelijke resultaten van een actie zijn afgeleid;
- regel 9: de methode [View] van de klasse [Controller] (regel 5) retourneert een type [ViewResult] dat is afgeleid van [ActionResult]. Deze methode kent talrijke overladingen. We zullen er een paar bekijken. De belangrijkste is de volgende:
![]() |
- de eerste parameter is de naam van de weergave. Als deze ontbreekt, wordt de weergave gebruikt die dezelfde naam draagt als de actie die de [ViewResult] genereert, en die wordt gezocht in de map [/Views/{controller}], waarbij {controller} de naam van de controller is;
- de tweede parameter is het sjabloon van de weergave. Als deze ontbreekt, heeft de weergave geen sjabloon.
De onderstaande methode [Index]:
public ActionResult Index()
{
return View();
}
vraagt de weergave [/Views/First/Index.cshtml] om te worden weergegeven. Er wordt geen sjabloon doorgegeven. Laten we [1] aanmaken in de map [/Views/First]:
![]() |
en laten we daarin de weergave [Index] [2] aanmaken:
![]() |
![]() |
We geven de naam van de weergave op als [3]. Deze wordt aangemaakt als [4]. De gegenereerde code is als volgt:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
</div>
</body>
</html>
Dit is klassieke HTML, behalve de regels 1-3, die uit C#-code bestaan. Het programma dat de weergaven beheert, wordt een weergave-engine genoemd. Deze zorgt ervoor dat alles wat geen HTML is, wordt omgezet in HTML. Dit is uiteindelijk wat naar de client wordt verzonden. De weergave-engine heet hier [Razor]. Hiermee kan C#-code in een weergave worden opgenomen. [Razor] interpreteert deze C#-code en genereert daaruit HTML-code. Hier volgen enkele basisregels voor het opnemen van C#-code in een weergave:
- de overgang van HTML naar C# vindt plaats bij het teken @ (regel 1). Als dit teken een codeblok inleidt, plaatsen we accolades (regels 1 en 3). Als het een variabele inleidt waarvan we de waarde willen ophalen, schrijven we simpelweg @variabele;
- de omschakeling van C# naar HTML vindt plaats bij het teken < (regel 5). Soms moet men deze omschakeling forceren, met name wanneer men platte tekst zonder HTML-tag in de pagina opneemt. Men gebruikt dan de <text>-tag om de tekst in te voegen: <text>hier platte tekst</text>.
Regel 2 hierboven geeft aan dat de weergave [Index] geen masterpagina heeft.
Laten we de weergave als volgt aanpassen:
@{
Layout = null;
string vue = "Index";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
<h3>Vue @vue</h3>
</div>
</body>
</html>
- regel 3: definieert een C#-variabele;
- regel 15: geeft de waarde van deze variabele weer.
Laten we nu de weergaven URL en [/First/Index] opvragen:
![]() |
De ontvangen code HTML is als volgt:
Dit is een puur HTML-document. Alle C#-code is verdwenen.
5.2. Gebruik [ViewBag] om informatie door te geven aan de weergave
We maken een nieuwe actie aan met de naam [Action01], gekoppeld aan de weergave [Action01.cshtml]:
![]() |
De actie [Action01] ziet er als volgt uit:
// Actie01
public ViewResult Action01()
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
return View();
}
- regel 4: we gebruiken de eigenschap [ViewBag] van de controller. Dit is een dynamisch object waaraan eigenschappen kunnen worden toegevoegd, zoals in regel 4 gebeurt. Dit object heeft de bijzonderheid dat het ook toegankelijk is voor de weergave. Het is dus een manier om informatie aan de weergave door te geven;
- regel 5: de standaardweergave van de actie wordt opgevraagd. Dit is de weergave [/First/Action01.cshtml]. Er wordt geen sjabloon doorgegeven.
De weergave [Action01.cshtml] ziet er als volgt uit:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action01</title>
</head>
<body>
<div>
<h4>@ViewBag.info</h4>
</div>
</body>
</html>
- regel 14: de eigenschap [ViewBag.info] wordt weergegeven.
Laten we het testen. We vragen de URL [/First/Action01] op:
![]() |
5.3. Een sterk getypeerd model gebruiken om informatie door te geven aan de weergave
De vorige methode heeft als nadeel dat fouten niet vóór de uitvoering kunnen worden opgespoord. Als de weergave [Action01.cshtml] dus de code
<h4>@ViewBag.Info</h4>
gebruikt, ontstaat er een fout omdat de eigenschap [Info] niet bestaat. De eigenschap die door de actie [Action01] wordt aangemaakt, heet [info]. We kunnen dan een sterk getypeerd model gebruiken om dit ongemak te voorkomen.
In een van de eerder besproken voorbeelden was de actie als volgt:
// Actie10
public ContentResult Action10(ActionModel03 modèle)
{
string erreurs = getErrorMessagesFor(ModelState);
string texte = string.Format("email={0}, jour={1}, info1={2}, info2={3}, info3={4}, erreurs={5}",
modèle.Email, modèle.Jour, modèle.Info1, modèle.Info2, modèle.Info3, erreurs);
return Content(texte, "text/plain", Encoding.UTF8);
}
De actie [Action10] stuurde zes gegevens (e-mail, dag, info1, info2, info3, fouten) in de vorm van een tekenreeks naar de client. We gaan deze informatie doorgeven in een weergavemodel [ViewModel01]. Aangezien dit model informatie overneemt van [ActionModel03], laten we het afleiden van deze klasse.
We beginnen met het kopiëren van [ActionModel03] uit het project [Exemple-02] naar het huidige project [Exemple-03]:
![]() |
en wijzigen de naamruimte zodat deze overeenkomt met die van het project [Exemple-03]:
using System.ComponentModel.DataAnnotations;
namespace Exemple_03.Models
{
public class ActionModel03
{
[Required(ErrorMessage = "Le paramètre email est requis")]
[EmailAddress(ErrorMessage = "Le paramètre email n'a pas un format valide")]
public string Email { get; set; }
[Required(ErrorMessage = "Le paramètre jour est requis")]
[RegularExpression(@"^\d{1,2}$", ErrorMessage = "Le paramètre jour doit avoir 1 ou 2 chiffres")]
public string Jour { get; set; }
[Required(ErrorMessage = "Le paramètre info1 est requis")]
[MaxLength(4, ErrorMessage = "Le paramètre info1 ne peut avoir plus de 4 caractères")]
public string Info1 { get; set; }
[Required(ErrorMessage = "Le paramètre info2 est requis")]
[MinLength(2, ErrorMessage = "Le paramètre info2 ne peut avoir moins de 2 caractères")]
public string Info2 { get; set; }
[Required(ErrorMessage = "Le paramètre info3 est requis")]
[MinLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
[MaxLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
public string Info3 { get; set; }
}
}
- regel 2: de nieuwe naamruimte;
Vervolgens maken we de klasse [ViewModel01] aan:
![]() |
De code van [ViewModel01] is als volgt:
namespace Exemple_03.Models
{
public class ViewModel01 : ActionModel03
{
public string Erreurs { get; set; }
}
}
- regel 3: de klasse erft van [ActionModel03] en dus ook van de eigenschappen van [Email, Jour, Info1, Info2, Info3];
- regel 5: we voegen de eigenschap [Erreurs] toe.
We schrijven nu de actie [Action02] die:
- als invoer het actiemodel [ActionModel03] accepteert;
- en als uitvoer het weergavemodel [ViewModel01] levert.
De code hiervoor is als volgt:
// Actie02
public ViewResult Action02(ActionModel03 modèle)
{
string erreurs = getErrorMessagesFor(ModelState);
return View(new ViewModel01(){Email=modèle.Email, Jour=modèle.Jour, Info1=modèle.Info1, Info2=modèle.Info2, Info3=modèle.Info3, Erreurs=erreurs});
}
- regel 1: [Action02] ontvangt het actiemodel [ActionModel03]. Het levert een resultaat van het type [ViewResult] op;
- regel 4: de fouten met betrekking tot het actiemodel [ActionModel03] worden samengevoegd in de tekenreeks [erreurs]. De methode [getErrorMessagesFor] is beschreven op pagina 65 en is opgenomen in de controller [First] van het nieuwe project;
- regel 5: de methode [View] wordt aangeroepen met één parameter. Dit is het model van de weergave. Deze is niet gespecificeerd. Er wordt dus gebruikgemaakt van de standaardweergave [/Views/First/Action02]. Het view-model [ViewModel01] wordt geïnstantieerd en geïnitialiseerd met de vijf gegevens uit het actiemodel [ActionModel03] en de in regel 4 geconstrueerde gegevens [erreurs].
We bouwen nu de weergave [/First/Action02.cshtml]:
![]() |
De code hiervoor is als volgt:
@model Exemple_03.Models.ViewModel01
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action02</title>
</head>
<body>
<h3>Informations du modèle de vue</h3>
<ul>
<li>Email : @Model.Email</li>
<li>Jour : @Model.Jour</li>
<li>Info1 : @Model.Info1</li>
<li>Info2 : @Model.Info2</li>
<li>Info3 : @Model.Info3</li>
<li>Erreurs : @Model.Erreurs</li>
</ul>
</body>
</html>
- de nieuwigheid zit in regel 1. De notatie [@model] bepaalt het type van het sjabloon van de weergave. Naar dit sjabloon wordt vervolgens verwezen met de notatie [@Model] (regels 16-21);
- regels 15-22: de informatie van het model wordt in een lijst weergegeven.
Laten we enkele voorbeelden bekijken van de uitvoering van de actie [Action02].
Eerst zonder parameters:
![]() |
vervolgens met onjuiste parameters:
![]() |
en vervolgens met de juiste parameters:
![]() |
In dit voorbeeld neemt het weergavemodel [ViewModel01] de informatie over van het actiemodel [ActionModel03]. Dit is vaak het geval. We kunnen dan één enkel model gebruiken dat zowel als actiemodel als weergavemodel dient. We maken een nieuw sjabloon aan: [ActionModel04]:
![]() |
dat er als volgt uitziet:
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace Exemple_03.Models
{
[Bind(Exclude="Erreurs")]
public class ActionModel04
{
// ---------------------- Actie --------------------------------
[Required(ErrorMessage = "Le paramètre email est requis")]
[EmailAddress(ErrorMessage = "Le paramètre email n'a pas un format valide")]
public string Email { get; set; }
[Required(ErrorMessage = "Le paramètre jour est requis")]
[RegularExpression(@"^\d{1,2}$", ErrorMessage = "Le paramètre jour doit avoir 1 ou 2 chiffres")]
public string Jour { get; set; }
[Required(ErrorMessage = "Le paramètre info1 est requis")]
[MaxLength(4, ErrorMessage = "Le paramètre info1 ne peut avoir plus de 4 caractères")]
public string Info1 { get; set; }
[Required(ErrorMessage = "Le paramètre info2 est requis")]
[MinLength(2, ErrorMessage = "Le paramètre info2 ne peut avoir moins de 2 caractères")]
public string Info2 { get; set; }
[Required(ErrorMessage = "Le paramètre info3 est requis")]
[MinLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
[MaxLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
public string Info3 { get; set; }
// ---------------------- weergave --------------------------------
public string Erreurs { get; set; }
}
}
- regels 8-28: het actiemodel met zijn integriteitsbeperkingen. Deze velden zullen ook deel uitmaken van de weergave;
- regel 31: een eigenschap die specifiek is voor het weergavemodel. Deze is uitgesloten van het actiemodel door de annotatie op regel 5.
We maken de volgende nieuwe actie [Action03] aan:
// Actie03
public ViewResult Action03(ActionModel04 modèle)
{
modèle.Erreurs = getErrorMessagesFor(ModelState);
return View(modèle);
}
- regel 2: [Action03] krijgt het actiemodel van het type [ActionModel04];
- regel 5: en geeft als weergavesjabloon datzelfde sjabloon terug;
- regel 4: aangevuld met de informatie [Erreurs];
Nu hoeven we alleen nog maar de weergave [/First/Action03.cshtml] aan te maken:
![]() |
- in [1]: klik met de rechtermuisknop op de code van [Action03] en vervolgens op [Ajouter une vue];
- naar [2]: de standaard voorgestelde naam van de weergave;
- in [3]: geef aan dat je een sterk getypeerde weergave aanmaakt;
- in [4]: selecteer de juiste klasse uit de vervolgkeuzelijst, in dit geval de klasse [ActionModel04];
- in [5]: de aangemaakte weergave.
We geven de weergave [Action03] dezelfde code als de weergave [Action02]. Alleen het weergavemodel (regel 1) en de paginatitel (regel 11) veranderen:
@model Exemple_03.Models.ActionModel04
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action03</title>
</head>
<body>
<h3>Informations du modèle de vue</h3>
<ul>
<li>Email : @Model.Email</li>
<li>Jour : @Model.Jour</li>
<li>Info1 : @Model.Info1</li>
<li>Info2 : @Model.Info2</li>
<li>Info3 : @Model.Info3</li>
<li>Erreurs : @Model.Erreurs</li>
</ul>
</body>
</html>
Laten we nu de actie [Action03] zonder parameters aanroepen:
![]() |
De resultaten zijn dezelfde als voorheen. Het komt vaak voor dat hetzelfde model wordt gebruikt voor zowel de actie als de weergave, omdat het weergavemodel vaak informatie uit het actiemodel overneemt. Er wordt dan een breder model gebruikt, dat zowel door de actie als door de weergave die deze genereert, kan worden gebruikt. We moeten ervoor zorgen dat informatie die niet tot het actiemodel behoort, uit de gegevenskoppeling wordt uitgesloten. Anders zou een goed geïnformeerde gebruiker zonder ons medeweten delen van het view-model kunnen initialiseren.
5.4. [Razor] – eerste stappen
We gaan nu enkele elementen van de weergaven [Razor] bespreken, voornamelijk de instructies foreach en if.
Stel dat we een lijst met personen willen weergeven in een tabel HTML. Het weergavesjabloon zou er als volgt uit kunnen zien: [ViewModel02]:
![]() |
namespace Exemple_03.Models
{
public class ViewModel02
{
public Personne[] Personnes { get; set; }
public ViewModel02()
{
Personnes = new Personne[] { new Personne { Nom = "Pierre", Age = 44 }, new Personne { Nom = "Pauline", Age = 12 } };
}
}
public class Personne
{
public string Nom { get; set; }
public int Age { get; set; }
}
}
- de weergave van het model is de klasse [ViewModel02], regels 3-10;
- regel 5: het model heeft een array van personen van het type [Personne], gedefinieerd in de regels 12-16;
- regels 6-10: de modelbouwer initialiseert de eigenschap [Personnes] van regel 5 met een array van twee personen.
De actie die dit model als uitvoer genereert, is de volgende: [Action04]:
// Actie04
public ViewResult Action04()
{
return View(new ViewModel02());
}
- regel 2: de actie heeft geen invoermodel;
- regel 4: de actie schakelt over naar de standaardweergave, een instantie van het model [ViewModel02] dat we zojuist hebben gedefinieerd.
De weergave [Action04.cshtml] zal het model [ViewModel02] weergeven:
![]() |
De code van de weergave [Action04.cshtml] is als volgt:
@model Exemple_03.Models.ViewModel02
@using Exemple_03.Models
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action04</title>
</head>
<body>
<table border="1">
<thead>
<tr>
<th>Nom</th>
<th>Age</th>
</tr>
</thead>
<tbody>
@foreach (Personne p in Model.Personnes)
{
<tr>
<td>@p.Nom</td>
<td>@p.Age</td>
</tr>
}
</tbody>
</table>
</body>
</html>
- regel 1: het sjabloon van de weergave;
- regel 2: de import van de naamruimte van de klasse [Personne] die op regel 24 wordt gebruikt;
- regels 16-32: de array HTML die de personen uit het model weergeeft;
- regel 24: het begin van de C#-code wordt aangegeven door het teken @. De instructie [foreach] doorloopt alle personen in het model;
- regels 26-27: het teken < beëindigt de C#-code en start de HTML-code. Vervolgens weer het teken @ om over te schakelen naar C# en de naam van de persoon te schrijven. Daarna weer het teken <, dat overschakelt naar de HTML-modus;
- regel 28: de leeftijd van de persoon wordt geschreven.
Het uitvoeren van de actie [Action04] levert het volgende resultaat op:
![]() |
Andere elementen van een weergave kunnen worden gevuld vanuit een verzameling: lijsten (al dan niet met een vervolgkeuzelijst), keuzerondjes en selectievakjes. Laten we het volgende nieuwe voorbeeld bekijken, waarin een vervolgkeuzelijst wordt weergegeven.
Het sjabloon [ViewModel05] ziet er als volgt uit:
![]() |
namespace Exemple_03.Models
{
public class ViewModel05
{
public Personne2[] Personnes { get; set; }
public int SelectedId { get; set; }
public ViewModel05()
{
Personnes = new Personne2[] {
new Personne2 { Id = 1, Prénom = "Pierre", Nom = "Martino" },
new Personne2 { Id = 2, Prénom = "Pauline", Nom = "Pereiro" },
new Personne2 { Id = 3, Prénom = "Jacques", Nom = "Alfonso" } };
SelectedId = 2;
}
}
public class Personne2
{
public int Id { get; set; }
public string Nom { get; set; }
public string Prénom { get; set; }
}
}
- regel 18: een klasse [Personne2] met drie eigenschappen;
- regel 3: het sjabloon [ViewModel05] van de weergave;
- regel 5: de lijst met personen die in de vervolgkeuzelijst moeten worden weergegeven in de vorm [Prénom Nom];
- regel 6: de [Id] van de persoon die in de vervolgkeuzelijst moet worden geselecteerd;
- regels 8-16: de constructor die een array met drie personen aanmaakt (regels 10-13) en de [Id] vaststelt van de persoon die geselecteerd moet worden weergegeven.
De weergave [Action05.cshtml] toont dit sjabloon:
![]() |
De code hiervoor is als volgt:
@model Exemple_03.Models.ViewModel05
@using Exemple_03.Models
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action05</title>
</head>
<body>
<select>
@foreach (Personne2 p in Model.Personnes)
{
string selected = "";
if (p.Id == Model.SelectedId)
{
selected = "selected=\"selected\"";
}
<option value="@p.Id" @selected>@p.Prénom @p.Nom</option>
}
</select>
</body>
</html>
De kenmerken van de keuzelijst HTML zijn beschreven in paragraaf 2.5.2.6. Laten we ze nog eens op een rijtje zetten:
Combo | <select size="1" name="cmbValeurs"> <option value="1">keuze1</option> <option selected="selected" value="2">keuze 2</option> <option value="3">keuze3</option> </select> |
tag HTML | <select size=".." name=".."> <option [selected="selected"] value=”v”>...</option> ... </select> geeft de teksten tussen de tags <option>...</option> |
attributen | name="cmbValeurs": naam van het besturingselement. size="1": aantal zichtbare lijstitems. size="1" maakt van de lijst het equivalent van een combobox. selected="selected": als dit trefwoord aanwezig is voor een lijstitem, wordt dit item geselecteerd weergegeven in de lijst. In ons voorbeeld hierboven verschijnt het lijstitem choix2 als het geselecteerde item van de combobox wanneer deze voor het eerst wordt weergegeven. value=”v”: als het element door de gebruiker wordt geselecteerd, wordt deze waarde [v] naar de server verzonden. Als dit attribuut ontbreekt, wordt de weergegeven en geselecteerde tekst naar de server verzonden. |
De code op de regels 17-25 genereert de tags <option> die worden geplaatst binnen de tag <select> op regel 16.
- regel 17: de lijst met personen uit het model wordt doorlopen;
- regel 20: er wordt gecontroleerd of de huidige persoon de persoon is die moet worden geselecteerd. Zo ja, dan wordt de tekst selected="selected" voorbereid die in de tag <option> moet worden ingevoegd;
- regel 24: de tag <option> wordt geschreven.
Laten we de actie [Action05] aanroepen:
![]() |
- in [1,2] worden de personen weergegeven in de vorm [Prénom Nom];
- In [1,2] is de geselecteerde persoon degene bij wie [Id] gelijk is aan 2.
Laten we nu eens kijken naar de broncode HTML van de bovenstaande pagina:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action05</title>
</head>
<body>
<select>
<option value="1" >Pierre Martino</option>
<option value="2" selected="selected">Pauline Pereiro</option>
<option value="3" >Jacques Alfonso</option>
</select>
</body>
</html>
- regels 10-12: de drie -tags die door de code [Razor] zijn gegenereerd;
- regel 11: het is inderdaad de persoon van [Id]=2 die is geselecteerd.
De twee bovenstaande voorbeelden volstaan. Bij het schrijven van een weergave [Razor] moet men de verleiding weerstaan om er logica in op te nemen. De C#-code zou dit toestaan. In het model MVC moet de logica echter in de actie of in de lagere lagen [Metier, DAO] zitten, maar niet in de weergave. Zelfs als je het model MVC volgt, kan er toch veel logica in de weergave terechtkomen om tussenwaarden te berekenen. Dit kan betekenen dat het gebruikte model niet gedetailleerd genoeg is. Het model moet de eindwaarden bevatten die de weergave nodig heeft, zodat deze ze niet zelf hoeft te berekenen. Een goede weergave is een weergave met zo min mogelijk logica, waarbij de structuur HTML van de weergave duidelijk blijft. Als er te veel C#-code wordt ingevoegd, kan de structuur HTML onleesbaar worden.
In het bovenstaande voorbeeld zou de keuzelijst door een gebruiker kunnen worden gebruikt en zouden we dan willen weten welke persoon hij heeft geselecteerd. Daarvoor hebben we een formulier nodig.
5.5. Formulier – eerste stappen
Het formulier dat aan de gebruiker wordt getoond, ziet er als volgt uit:
![]() |
Het weergavemodel is het model [ViewModel05] dat eerder al is gebruikt. De actie die deze weergave weergeeft, is de volgende:
// Actie06-GET
[HttpGet]
public ViewResult Action06()
{
return View("Action06Get",new ViewModel05());
}
- regel 2: de actie kan alleen worden aangeroepen door een commando HTTP GET;
- regel 5: de weergave [/First/Action06Get.cshtml] wordt weergegeven op basis van een instantie van het type [ViewModel05].
De weergave [/First/Action06Get.cshtml] ziet er als volgt uit:
![]() |
@model Exemple_03.Models.ViewModel05
@using Exemple_03.Models
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action06-GET</title>
</head>
<body>
<h3>Action06 - GET</h3>
<p>Choisissez une personne</p>
<form method="post" action="/First/Action06">
<select name="personneId">
@foreach (Personne2 p in Model.Personnes)
{
string selected = "";
if (p.Id == Model.SelectedId)
{
selected = "selected=\"selected\"";
}
<option value="@p.Id" @selected>@p.Prénom @p.Nom</option>
}
</select>
<input name="valider" type="submit" value="Valider" />
</form>
</body>
</html>
De belangrijkste nieuwigheden zijn de volgende:
- regel 18: om ervoor te zorgen dat de browser de door een gebruiker ingevoerde gegevens kan doorsturen, hebben we een formulier nodig. Dit wordt afgebakend door de tag <form> op de regels 18 en 31.
De tag HTML <form> is in paragraaf 2.5.2.1 besproken. Laten we de kenmerken ervan nog eens op een rijtje zetten:
formulier | |
tag HTML | <form name="..." method="..." action="...">...</form> |
attributen | name="frmexemple": naam van het formulier – optioneel method="..." : methode die door de browser wordt gebruikt om de in het formulier verzamelde waarden naar de webserver te verzenden action="...": URL waarnaar de in het formulier verzamelde waarden worden verzonden. Een webformulier wordt omgeven door de <form>...</form>-tags. Het formulier kan een naam hebben (name="xx"). Dit geldt voor alle besturingselementen die in een formulier voorkomen. Het doel van een formulier is om informatie te verzamelen die de gebruiker via het toetsenbord of de muis invoert, en deze naar een URL van een webserver te verzenden. Welke? Die waarnaar wordt verwezen in het attribuut action="URL". Als dit attribuut ontbreekt, wordt de informatie verzonden naar de URL van het document waarin het formulier zich bevindt. Een webclient kan twee verschillende methoden gebruiken, namelijk POST en GET, om gegevens naar een webserver te verzenden. Het attribuut method="méthode", waarbij method gelijk is aan GET of POST, van de tag <form> geeft aan de browser aan welke methode moet worden gebruikt om de in het formulier verzamelde informatie te verzenden naar de URL die is opgegeven door het attribuut action="URL". Wanneer het attribuut method niet is opgegeven, wordt standaard de methode GET gebruikt. |
- regel 18: we zien dat de waarden van het formulier via een commando HTTP POST naar de URL [/First/Action06] worden verzonden;
- regel 30: een formulier moet een knop van het type [submit] bevatten. Deze knop zorgt ervoor dat de ingevoerde waarden worden verzonden naar de URL die is opgegeven door het attribuut [action] van de tag <form>.
Wat verstuurt de browser precies wanneer de gebruiker op de knop [Valider] klikt? Dit is uitgelegd in paragraaf 2.5.3.1. Laten we even herhalen wat daar is gezegd:
besturingselement HTML | visueel | teruggestuurde waarde(n) |
<input type="radio" value="Ja" name="R1"/>Ja <input type="radio" name="R1" value="nee" checked="checked"/>Nee | R1=Ja - de waarde van het attribuut value van de door de gebruiker aangevinkte keuzeknop. | |
<input type="checkbox" name="C1" value="één"/>1 <input type="checkbox" name="C2" value="twee" checked="checked"/>2 <input type="checkbox" name="C3" value="drie"/>3 | C1=één C2=twee - waarden van de attributen value van de door de gebruiker aangevinkte selectievakjes | |
<input type="text" name="txtSaisie" size="20" value="enkele woorden"/> | txtSaisie=webprogrammering - tekst die door de gebruiker in het invoerveld is getypt. De spaties zijn vervangen door het teken + | |
<input type="password" name="txtMdp" size="20" value="unMotDePasse"/> | txtMdp=ditisgeheim - tekst die door de gebruiker in het invoerveld is getypt | |
<textarea rows="2" name="areaSaisie" cols="20"> regel1 regel2 regel3 </textarea> | invoergebied=de+basisprincipes+van+de%0D%0A webprogrammering+ - tekst die door de gebruiker in het invoerveld is getypt. %OD%OA is het teken voor het einde van de regel. De spaties zijn vervangen door het teken + | |
<select size="1" name="cmbValeurs"> <option value='1'>keuze1</option> <option selected="selected" value='2'>keuze2</option> <option value='3'>keuze3</option> </select> | cmbWaarden=3 - attribuut [value] van het door de gebruiker geselecteerde element | |
<select size="3" name="lst1"> <option selected="selected" value='1'>lijst1</option> <option value='2'>lijst2</option> <option value='3'>lijst3</option> <option value='4'>lijst4</option> <option value='5'>lijst5</option> </select> | ![]() | lst1=3 - attribuut [value] van het door de gebruiker geselecteerde element |
<select size="3" name="lst2" multiple="multiple"> <option selected="selected" value='1'>lijst1</option> <option value='2'>lijst2</option> <option selected="selected" value='3'>lijst3</option> <option value='4'>lijst4</option> <option value='5'>lijst5</option> </select> | lst2=1 lst2=3 - attributen [value] van de door de gebruiker geselecteerde elementen | |
<input type="submit" value="Verzenden" name="cmdRenvoyer"/> | cmdVerzenden=Verzenden - naam en attribuut value van de knop waarmee de formuliergegevens naar de server zijn verzonden | |
<input type="hidden" name="secret" value="uneValeur"/> | secret=eenWaarde - attribuut value van het verborgen veld |
In ons formulier hebben we twee tags die een waarde kunnen verzenden:
<select name="personneId">
...
</select>
en
<input name="valider" type="submit" value="Valider" />
Als de gebruiker persoon nr. 2 selecteert, worden de waarden als volgt verzonden:
De namen van de parameters zijn dezelfde als die van de attributen [name] van de tags waarop POST betrekking heeft. Zonder dit attribuut geven de tags geen waarde door. Zo zou men hierboven het attribuut name="valider" van de knop [submit] kunnen weglaten. De verzonden waarde is het attribuut [value] van de knop. Deze informatie is hier niet van belang. Soms hebben formulieren meerdere knoppen van het type [submit]. Het is dan belangrijk om te weten op welke knop is geklikt. We zullen dan het attribuut [name] aan de verschillende knoppen toekennen.
De tag <select> bestaat uit een reeks <option>-tags:
<select name="personneId">
<option value="1" >Pierre Martino</option>
<option value="2" selected="selected">Pauline Pereiro</option>
<option value="3" >Jacques Alfonso</option>
</select>
De waarde van het attribuut [value] van de geselecteerde optie wordt verzonden. Als dit attribuut ontbreekt, wordt de tekst weergegeven die bij de optie hoort, bijvoorbeeld [Pierre Martino], verzonden.
De tekenreeks
wordt gepost naar de volgende URL [/First/Action06]:
// Actie06-POST
[HttpPost]
public ViewResult Action06(ActionModel06 modèle)
{
return View("Action06Post",modèle);
}
Misschien herinner je je nog dat we al een actie [Action06] hadden:
// Actie06-GET
[HttpGet]
public ViewResult Action06()
{
return View("Action06Get",new ViewModel05());
}
Het is mogelijk om twee acties met dezelfde naam te hebben, op voorwaarde dat ze niet dezelfde opdrachten verwerken: HTTP:
- [Action06] op regel 3 verwerkt een POST (regel 2);
- [Action06] op regel c verwerkt een GET (regel b).
De actie [Action06] die de POST beheert, ontvangt de volgende reeks parameters:
We hebben een actiemodel nodig om deze waarden in te kapselen. Dit wordt het volgende model [ActionModel06]:
![]() |
using System.ComponentModel.DataAnnotations;
namespace Exemple_03.Models
{
public class ActionModel06
{
[Required(ErrorMessage = "Le paramètre [personneId] est requis")]
public int PersonneId { get; set; }
[Required(ErrorMessage = "Le paramètre [valider] est requis")]
public string Valider { get; set; }
}
}
De actie [Action06] ontvangt dit sjabloon en geeft het ongewijzigd door aan de volgende weergave [Action06Post] (regel 5 van de actie):
![]() |
@model Exemple_03.Models.ActionModel06
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action06Post</title>
</head>
<body>
<h3>Action06 - POST</h3>
Valeurs postées :
<ul>
<li>ID de la personne sélectionnée : @Model.PersonneId</li>
<li>Commande utilisée : @Model.Valider</li>
</ul>
</body>
</html>
Het sjabloon wordt weergegeven op de regels 18 en 19.
Laten we eens een voorbeeld bekijken:
![]() |
In [1] wordt de derde persoon van [Id] geselecteerd, wat gelijk is aan 3. In [2] wordt het formulier verzonden. In [3] worden de ontvangen waarden weergegeven. In [4,5] zien we dat dezelfde URL is aangeroepen, de ene door een GET [4], de andere door een POST en [5]. Dit is niet te zien in de URL.
In de weergave die na de POST wordt getoond, zou men misschien liever de nom en prénom van de geselecteerde persoon zien in plaats van zijn nummer. De weergave van het POST en het bijbehorende model moeten dan worden aangepast.
We maken een actie [Action07] aan om dit geval af te handelen. Deze actie moet de sessie van de gebruiker gebruiken om daar de lijst met personen op te slaan. We volgen het model dat in paragraaf 4.10 is besproken, waarmee de gegevens uit de scopes [Application] en [Session] in het model van de actie kunnen worden opgenomen.
Het sessiemodel wordt de volgende klasse [SessionModel]:
![]() |
namespace Exemple_03.Models
{
public class SessionModel
{
public Personne2[] Personnes { get; set; }
}
}
- regel 2: de sessie slaat de lijst met personen op die in de vervolgkeuzelijst worden weergegeven;
We moeten het vorige type [SessionModel] koppelen aan een binder die we [SessionModelBinder] zullen noemen. Deze zal dezelfde zijn als die beschreven op pagina 82:
![]() |
using System.Web.Mvc;
namespace Exemple_03.Infrastructure
{
public class SessionModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// we geven de gegevens van het bereik [Session] terug
return controllerContext.HttpContext.Session["data"];
}
}
}
De koppeling tussen het model [SessionModel] en zijn binder [SessionModelBinder] vindt plaats in [Global.asax]:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
...
// modelbinders
ModelBinders.Binders.Add(typeof(SessionModel), new SessionModelBinder());
}
// Sessie
public void Session_Start()
{
Session["data"] = new SessionModel();
}
}
- regel 8: de koppeling van het model aan zijn binder vindt plaats in [Application_Start];
- regel 13: er wordt een instantie van het type [SessionModel] in de sessie geplaatst, gekoppeld aan de sleutel [data].
Vervolgens is de actie [Action07] als volgt:
// Actie07-GET
[HttpGet]
public ViewResult Action07(SessionModel session)
{
ViewModel05 modèleVue = new ViewModel05();
session.Personnes= modèleVue.Personnes;
return View("Action07Get", modèleVue);
}
- regel 3: de actie haalt een type [SessionModel] op, dus de scope-gegevens [Session] die gekoppeld zijn aan de sleutel [data];
- regel 5: het weergavemodel wordt aangemaakt;
- regel 6: de tabel met personen wordt in de sessie geplaatst. Deze is nodig voor de volgende query, namelijk die van POST. Het protocol HTTP is een stateloos protocol. Er moet een sessie worden gebruikt om geheugen te behouden tussen de verzoeken. Een sessie is specifiek voor een gebruiker en wordt beheerd door de webserver;
- regel 7: de weergave [Action07Get.cshtml] wordt weergegeven. Deze ziet er als volgt uit:
@model Exemple_03.Models.ViewModel05
@using Exemple_03.Models
...
<body>
<h3>Action07 - GET</h3>
<p>Choisissez une personne</p>
<form method="post" action="/First/Action07">
....
</form>
</body>
</html>
Deze is identiek aan de reeds besproken weergave [Action06Get.cshtml]. Het belangrijkste verschil bevindt zich op regel 7: de URL waarnaar de waarden van het formulier worden verzonden. Deze worden verwerkt door de volgende actie [Action07]:
// Actie07-POST
[HttpPost]
public ViewResult Action07(SessionModel session, ActionModel06 modèle)
{
Personne2 personne = session.Personnes.Where(p => p.Id == modèle.PersonneId).First<Personne2>();
string strPersonne = string.Format("{0} {1}", personne.Prénom, personne.Nom);
return View("Action07Post", (object)strPersonne);
}
- regel 3: de verzonden waarden worden ingekapseld in het actiemodel [ActionModel06] dat eerder al is gebruikt (zie hieronder):
using System.ComponentModel.DataAnnotations;
namespace Exemple_03.Models
{
public class ActionModel06
{
[Required(ErrorMessage = "Le paramètre [personneId] est requis")]
public int PersonneId { get; set; }
[Required(ErrorMessage = "Le paramètre [valider] est requis")]
public string Valider { get; set; }
}
}
- regel 3: de eerste parameter is het bereikgegeven [Session] dat gekoppeld is aan de sleutel [data];
- regel 5: een verzoek LINQ haalt de persoon op met de [Id] die is gepost;
- regel 6: we stellen de tekenreeks samen die door de weergave [Action07Post] moet worden weergegeven (regel 8);
- regel 7: om de juiste constructor [View] aan te roepen, moet het type [string] worden omgezet naar [object].
De weergave [Action07Post.cshtml] ziet er als volgt uit:
@model string
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action07-Post</title>
</head>
<body>
<h3>Action07-POST</h3>
Vous avez sélectionné [@Model].
</body>
</html>
- regel 1: het model is van het type [string];
- regel 16: de tekenreeks wordt weergegeven.
Hier volgt een uitvoervoorbeeld:
![]() | ![]() |
5.6. Formulier – een volledig voorbeeld
In paragraaf 2.5.2.1 hebben we het volgende formulier HTML besproken:
1 ![]() |
We gaan een actie [Action08Get] bekijken die dit formulier (GET) weergeeft, en een actie [Action08Post] die de door de gebruiker ingevoerde waarden (POST) verwerkt. Een klassiek schema.
Het sjabloon van de bovenstaande weergave [1] zal een instantie zijn van de klasse [ViewModel08]. Deze klasse zal tegelijkertijd:
- het model van de weergave die wordt gegenereerd door een GET op de actie [Action08Get];
- het model van de actie [Action08Post] voor een verzoek POST.
![]() |
![]() |
5.6.1. Het bereikmodel [Application]
We gaan ervan uit dat de elementen die worden weergegeven door de keuzerondjes, de selectievakjes en de verschillende lijsten gegevens uit het bereik [Application] zijn. Dit komt vaak voor. Deze informatie is afkomstig uit een configuratiebestand of een database die bij het opstarten van de applicatie wordt gebruikt in de methode [Application_Start] van [Global.asax]. Deze methode verloopt als volgt:
protected void Application_Start()
{
....
// modelbinders
ModelBinders.Binders.Add(typeof(SessionModel), new SessionModelBinder());
ModelBinders.Binders.Add(typeof(ApplicationModel), new ApplicationModelBinder());
// scope-gegevens [Application]
Application["data"] = new ApplicationModel();
}
- regel 7: het type [ApplicationModel], dat we straks zullen beschrijven, wordt gekoppeld aan de gegevensbinder [ApplicationModelBinder], die we al op pagina 82 hebben besproken;
- regel 10: een instantie van het type [ApplicationModel] wordt opgeslagen in het applicatiewoordenboek, gekoppeld aan de sleutel [data].
De klasse [ApplicationModel] dient om alle gegevens van het bereik [Application] in te kapselen. Hier zal deze de gegevens inkapselen die het formulier moet weergeven:
![]() |
namespace Exemple_03.Models
{
public class ApplicationModel
{
// de collecties die in het formulier moeten worden weergegeven
public Item[] RadioButtonFieldItems { get; set; }
public Item[] CheckBoxesFieldItems { get; set; }
public Item[] DropDownListFieldItems { get; set; }
public Item[] SimpleChoiceListFieldItems { get; set; }
public Item[] MultipleChoiceListFieldItems { get; set; }
// initialisatie van velden en collecties
public ApplicationModel()
{
RadioButtonFieldItems = new Item[]{
new Item {Value="1",Label="oui"},
new Item {Value="2", Label="non"}
};
CheckBoxesFieldItems = new Item[]{
new Item {Value="1",Label="1"},
new Item {Value="2", Label="2"},
new Item {Value="3", Label="3"}
};
DropDownListFieldItems = new Item[]{
new Item {Value="1",Label="choix1"},
new Item {Value="2", Label="choix2"},
new Item {Value="3", Label="choix3"}
};
SimpleChoiceListFieldItems = new Item[]{
new Item {Value="1",Label="liste1"},
new Item {Value="2", Label="liste2"},
new Item {Value="3", Label="liste3"},
new Item {Value="4", Label="liste4"},
new Item {Value="5", Label="liste5"}
};
MultipleChoiceListFieldItems = new Item[]{
new Item {Value="1",Label="liste1"},
new Item {Value="2", Label="liste2"},
new Item {Value="3", Label="liste3"},
new Item {Value="4", Label="liste4"},
new Item {Value="5", Label="liste5"}
};
}
// het element van de collecties
public class Item
{
public string Label { get; set; }
public string Value { get; set; }
}
}
}
- regels 45-49: het element van de verschillende collecties van het formulier. [Label] is de tekst die door het formulierelement wordt weergegeven, [Value] de waarde die door dit element wordt verzonden wanneer het wordt geselecteerd;
- regel 6: de verzameling die door de keuzeknop wordt weergegeven;
- regel 7: de verzameling die door de selectievakjes wordt weergegeven;
- regel 8: de lijst die door de vervolgkeuzelijst wordt weergegeven;
- regel 9: de verzameling die wordt weergegeven door de lijst met enkele selectie;
- regel 10: de verzameling die wordt weergegeven door de lijst met meervoudige selectie;
- regels 13-43: deze collecties worden geïnitialiseerd door de constructor zonder parameters van de klasse.
De verschillende collecties zullen het volgende formulier vullen:
![]() |
5.6.2. Het model van de actie [Action08Get]
Het voorgaande formulier wordt weergegeven door de volgende actie [Action08Get]:
// Action08-GET
[HttpGet]
public ViewResult Action08Get(ApplicationModel application)
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
return View("Formulaire", new ViewModel08(application));
}
- regel 2: [Action08Get] reageert alleen op een opdracht [GET];
- regel 3: deze ontvangt als parameter het zojuist beschreven applicatiemodel;
- regel 5: deze initialiseert een gegeven in de dynamische container [ViewBag];
- regel 6: de functie geeft de weergave [/First/Formulaire.cshtml] weer met het model [ViewModel08]. Dit model is dat van het eerder getoonde formulier. Hiervoor wordt het applicatiemodel, dat de weer te geven elementen definieert, doorgegeven aan de constructor.
5.6.3. Het model van de weergave [Formulaire]
De klasse [ViewModel08] zal het model van het formulier zijn. Deze klasse ziet er als volgt uit:
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Exemple_03.Models;
namespace Exemple_03.Models
{
public class ViewModel08
{
// de invoervelden
public string RadioButtonField { get; set; }
public string[] CheckBoxesField { get; set; }
public string TextField { get; set; }
public string PasswordField { get; set; }
public string TextAreaField { get; set; }
public string DropDownListField { get; set; }
public string SimpleChoiceListField { get; set; }
public string[] MultipleChoiceListField { get; set; }
// de collecties die in het formulier moeten worden weergegeven
public ApplicationModel.Item[] RadioButtonFieldItems { get; set; }
public ApplicationModel.Item[] CheckBoxesFieldItems { get; set; }
public ApplicationModel.Item[] DropDownListFieldItems { get; set; }
public ApplicationModel.Item[] SimpleChoiceListFieldItems { get; set; }
public ApplicationModel.Item[] MultipleChoiceListFieldItems { get; set; }
// constructors
public ViewModel08()
{
}
public ViewModel08(ApplicationModel application)
{
// initialisatie van collecties
RadioButtonFieldItems = application.RadioButtonFieldItems;
CheckBoxesFieldItems = application.CheckBoxesFieldItems;
DropDownListFieldItems = application.DropDownListFieldItems;
SimpleChoiceListFieldItems = application.SimpleChoiceListFieldItems;
MultipleChoiceListFieldItems = application.MultipleChoiceListFieldItems;
// initialisatie van velden
RadioButtonField = "2";
CheckBoxesField = new string[] { "2" };
TextField = "quelques mots";
PasswordField = "secret";
TextAreaField = "ligne1\nligne2";
DropDownListField = "2";
SimpleChoiceListField = "3";
MultipleChoiceListField = new string[] { "1", "3" };
}
}
}
- in een formulier zijn er twee soorten elementen: elementen die worden weergegeven en elementen die kunnen worden ingevuld;
- de regels 20-24 definiëren de elementen die moeten worden weergegeven. Dit zijn de verschillende verzamelingen van het formulier. Deze zijn te vinden in het model van de applicatie (regels 34-38);
- regels 10-17: definiëren de invoervelden van het formulier;
- regel 10: [RadioButtonField] haalt de waarde op die door de volgende regels van het formulier wordt verzonden:
<!-- de keuzerondjes -->
<tr>
<td>Etes-vous marié(e)</td>
<td>
<input type="radio" name="RadioButtonField" value="1" />oui
<input type="radio" name="RadioButtonField" value="2" checked="checked"/>non
</td>
</tr>
Let op: in de regels 5 en 6 is het attribuut [name] van de twee keuzerondjes de naam van de eigenschap die zal worden geïnitialiseerd. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&RadioButtonField=2¶m2=val2
als de gebruiker de optie met de naam [non] heeft aangevinkt. Het is namelijk het attribuut [value] van de aangevinkte optie dat wordt verzonden.
- regel 11: [CheckBoxesField] haalt de waarden op die door de volgende regels van het formulier zijn verzonden:
<!-- selectievakjes -->
<tr>
<td>Cases à cocher</td>
<td>
<input type="checkbox" name="CheckBoxesField" value="1" />1
<input type="checkbox" name="CheckBoxesField" value="2" checked="checked"/>2
<input type="checkbox" name="CheckBoxesField" value="3" />3
</td>
Let op: in de regels 5 en 6 is het attribuut [name] van de selectievakjes de naam van de eigenschap die zal worden geïnitialiseerd. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&CheckBoxesField=2&CheckBoxesField=3¶m2=val2
als de gebruiker de selectievakjes met de labels [2] en [3] heeft aangevinkt. Het is het attribuut [value] van de aangevinkte opties dat wordt verzonden. Omdat er meerdere parameters met dezelfde naam kunnen worden verzonden, is [CheckBoxesField] een array van waarden en geen enkele waarde. Als er geen vakje is aangevinkt, ontbreekt de parameter [CheckBoxesField] in de verzonden string en wordt de eigenschap met dezelfde naam in het model niet geïnitialiseerd. Dit kan lastig zijn, zoals we zullen zien.
- regel 12: [TextField] haalt de waarde op die door de volgende regels van het formulier wordt verzonden:
<!-- het tekstinvoerveld voor één regel -->
<tr>
<td>Champ de saisie</td>
<td>
<input type="text" name="TextField" value="quelques mots" size="30" />
</td>
</tr>
Regel 5: het attribuut [name] van het invoerveld is de naam van de eigenschap die zal worden geïnitialiseerd. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&TextField=abcdef¶m2=val2
als de gebruiker [abcdef] in het invoerveld heeft ingevoerd.
- regel 13: [PasswordField] haalt de waarde op die door de volgende regels van het formulier is verzonden:
<!-- het wachtwoordveld -->
<tr>
<td>Mot de passe</td>
<td>
<input type="password" name="PasswordField" value="secret" size="30" />
</td>
</tr>
Regel 5: het attribuut [name] van het invoerveld is de naam van de eigenschap die zal worden geïnitialiseerd. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&PasswordField=abcdef¶m2=val2
als de gebruiker [abcdef] in het invoerveld heeft ingevoerd.
- regel 14: [TextAreaField] haalt de waarde op die is verzonden via de volgende regels van het formulier:
<!-- het tekstinvoerveld voor meerdere regels -->
<tr>
<td>Boîte de saisie</td>
<td>
<textarea name="TextAreaField" cols="40" rows="3">ligne1
ligne2</textarea>
</td>
</tr>
Regel 5: het attribuut [name] van het invoerveld is de naam van de eigenschap die zal worden geïnitialiseerd. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&TextAreaField=abcdef%0D%OAhijk¶m2=val2
als de gebruiker [abcdef] gevolgd door een regeleinde en [ijk] in het invoerveld heeft ingevoerd.
- regel 15: [DropDownListField] haalt de waarde op die is verzonden via de volgende regels van het formulier:
<!-- de vervolgkeuzelijst -->
<tr>
<td>Liste déroulante</td>
<td>
<select name="DropDownListField">
<option value="1" >choix1</option>
<option value="2" selected="selected">choix2</option>
<option value="3" >choix3</option>
</select>
</tr>
Regel 5: het attribuut [name] van de tag <select> is de naam van de eigenschap die zal worden geïnitialiseerd. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&DropDownListField=1¶m2=val2
als de gebruiker de optie [choix1] heeft geselecteerd. Het is het attribuut [value] van de geselecteerde optie dat wordt verzonden.
- regel 16: [SingleChoiceListField] haalt de waarde op die door de volgende regels van het formulier is verzonden:
<!-- de lijst met één keuze -->
<tr>
<td>Liste à choix unique</td>
<td>
<select name="SimpleChoiceListField" size="3">
<option value="1" >liste1</option>
<option value="2" >liste2</option>
<option value="3" selected="selected">liste3</option>
<option value="4" >liste4</option>
<option value="5" >liste5</option>
</select>
</tr>
Regel 5: het attribuut [name] van de tag <select> is de naam van de eigenschap die zal worden geïnitialiseerd. Het is het attribuut [size="3"] dat ervoor zorgt dat er geen vervolgkeuzelijst wordt weergegeven. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&SimpleChoiceListField=3¶m2=val2
als de gebruiker de optie [liste3] heeft geselecteerd. Het is het attribuut [value] van de geselecteerde optie dat wordt verzonden. De parameter [SingleChoiceListField] kan ontbreken in de verzonden tekenreeks als er geen element is geselecteerd.
- regel 17: [MultipleChoiceListField] haalt de waarden op die door de volgende regels van het formulier zijn verzonden:
<!-- de meerkeuzelijst -->
<tr>
<td>Liste à choix multiple</td>
<td>
<select name="MultipleChoiceListField" size="3" multiple="multiple">
<option value="1" selected="selected">liste1</option>
<option value="2" >liste2</option>
<option value="3" selected="selected">liste3</option>
<option value="4" >liste4</option>
<option value="5" >liste5</option>
</select>
</tr>
Regel 5: het attribuut [name] van de tag <select> is de naam van de eigenschap die zal worden geïnitialiseerd. Het is het attribuut [size="3"] dat ervoor zorgt dat er geen vervolgkeuzelijst is, en het attribuut [multiple] dat ervoor zorgt dat de gebruiker meerdere elementen kan selecteren door de toets [Ctrl] ingedrukt te houden. In de verzonden gegevens vinden we een tekenreeks in de vorm:
param1=val1&MultipleChoiceListField=1&MultipleChoiceListField=3¶m2=val2
als de gebruiker de opties [liste1] en [liste3] heeft geselecteerd. Het is het attribuut [value] van de geselecteerde opties dat wordt verzonden. Omdat er meerdere parameters met dezelfde naam kunnen worden verzonden, is [MultipleChoiceListField] een array van waarden en geen enkele waarde. Als er geen vakje is aangevinkt, ontbreekt de parameter [MultipleChoiceListField] in de verzonden tekenreeks en wordt de eigenschap met dezelfde naam in het model niet geïnitialiseerd.
De verschillende invoervelden die hierboven zijn weergegeven, zullen de door het formulier verzonden waarden ontvangen. Ze kunnen ook worden geïnitialiseerd voordat het formulier wordt verzonden. Dat is hier gedaan:
// velden initialiseren
RadioButtonField = "2";
CheckBoxesField = new string[] { "2" };
TextField = "quelques mots";
PasswordField = "secret";
TextAreaField = "ligne1\nligne2";
DropDownListField = "2";
SimpleChoiceListField = "3";
MultipleChoiceListField = new string[] { "1", "3" };
Als deze waarden waren verkregen na het verzenden van het formulier met POST, zou dit betekenen dat de gebruiker:
- regel 2: de optie [non] van de keuzeknop heeft aangevinkt;
- regel 3: de optie [2] bij de selectievakjes aangevinkt;
- regel 4: [quelques mots] in het invoerveld heeft getypt;
- regel 5: [secret] als wachtwoord ingevoerd;
- regel 6: [ligne1\nligne2] ingevoerd in het invoerveld voor meerdere regels;
- regel 7: de optie [choix2] geselecteerd uit de vervolgkeuzelijst;
- regel 8: de optie [liste3] geselecteerd uit de lijst met één keuze;
- regel 9: de opties [liste1] en [liste3] geselecteerd uit de lijst met meerdere keuzemogelijkheden;
We gaan ervan uit dat er een POST heeft plaatsgevonden en dat we het formulier willen terugsturen zoals het is ingevuld. Dit gebeurt met name wanneer een foutief ingevuld formulier naar de gebruiker wordt teruggestuurd. Het formulier wordt dan teruggestuurd zoals het is ingevuld.
5.6.4. De weergave [Formulaire]
De weergave [/First/Formulaire.cshtml] toont het formulier:
![]() |
@model Exemple_03.Models.ViewModel08
@using Exemple_03.Models
@{
Layout = null;
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Formulaire</title>
</head>
<body>
<form method="post" action="Action08Post">
<h2>Formulaire ASP.NET MVC</h2>
<h3>Affiché par : @ViewBag.info</h3>
<table>
<thead></thead>
<tbody>
<!-- keuzerondjes -->
<tr>
<td>Etes-vous marié(e)</td>
<td>
@foreach (ApplicationModel.Item item in @Model.RadioButtonFieldItems)
{
string strChecked = item.Value == @Model.RadioButtonField ? "checked=\"checked\"" : "";
<input type="radio" name="RadioButtonField" value="@item.Value" @strChecked/>@item.Label
<text/>
}
</td>
</tr>
...
</tbody>
</table>
<input type="submit" value="Valider" />
</form>
</body>
</html>
- regel 1: [ViewModel08] is het sjabloon van het formulier;
- regel 12: de tag <form> van het formulier. Dit formulier wordt verzonden met de methode [POST] (attribuut method) naar de URL [/First/Action08Post] (attribuut action);
- regel 33: de knop van het type [submit] die dient om het formulier te verzenden;
- regels 22-27: geven de keuzerondjes weer:
- regel 22: er wordt door de verzameling gebladerd die door de keuzeknop wordt weergegeven;
- regel 24: de knop waarvan het attribuut [value] de waarde van de eigenschap [RadioButtonField] heeft, moet worden aangevinkt. Hiervoor moet deze het attribuut [checked="checked"] hebben;
- regel 25: genereren van de tag <input type="radio"> met als waarde [@item.Value] en als label [@item.Label];
- regel 26: de tag <text/> is geen herkende HTML-tag. Deze is bedoeld voor [Razor]. Wanneer deze wordt aangetroffen, genereert [Razor] een regeleinde. Dit heeft geen invloed op het weergegeven formulier, maar wel op de gegenereerde code HTML. De tags <input type="radio"> staan dan op twee verschillende regels in plaats van op dezelfde regel. Dit maakt de code beter leesbaar wanneer men in de browser vraagt om de broncode van de weergegeven pagina te bekijken;
We bekijken nu de overige elementen van de weergave:
<!-- selectievakjes -->
<tr>
<td>Cases à cocher</td>
<td>
@{
foreach (ApplicationModel.Item item in @Model.CheckBoxesFieldItems)
{
string strChecked = @Model.CheckBoxesField.Contains(item.Value) ? "checked=\"checked\"" : "";
<input type="checkbox" name="CheckBoxesField" value="@item.Value" @strChecked/>@item.Label
<text/>
}
}
</td>
- regel 6: we doorlopen de verzameling die door de selectievakjes wordt weergegeven;
- regel 8: een vakje met het attribuut [value] moet worden aangevinkt als het een van de waarden van de eigenschap [CheckBoxesField] heeft. Hiervoor moet het het attribuut [checked="checked"] hebben. Er wordt een uitdrukking LINQ gebruikt om te bepalen of een waarde in een array voorkomt;
- regel 25: genereren van de tag <input type="checkbox"> met als waarde [@item.Value] en als label [@item.Label];
<!-- het tekstinvoerveld voor één regel -->
<tr>
<td>Champ de saisie</td>
<td>
<input type="text" name="TextField" value="@Model.TextField" size="30" />
</td>
</tr>
<!-- het wachtwoordveld -->
<tr>
<td>Mot de passe</td>
<td>
<input type="password" name="PasswordField" value="@Model.PasswordField" size="30" />
</td>
</tr>
<!-- het tekstinvoerveld voor meerdere regels -->
<tr>
<td>Boîte de saisie</td>
<td>
<textarea name="TextAreaField" cols="40" rows="3">@Model.TextAreaField</textarea>
</td>
</tr>
- regels 5, 12: het attribuut [value] van de tag krijgt de waarde van het sjabloon;
- regel 19: idem, maar met een andere syntaxis.
<!-- de vervolgkeuzelijst -->
<tr>
<td>Liste déroulante</td>
<td>
<select name="DropDownListField">
@{
foreach (ApplicationModel.Item item in @Model.DropDownListFieldItems)
{
string strChecked = item.Value == @Model.DropDownListField ? "selected=\"selected\"" : "";
<option value="@item.Value" @strChecked>@item.Label</option>
}
}
</select>
</tr>
- regel 7: de collectie die door de vervolgkeuzelijst wordt weergegeven, wordt doorlopen;
- regel 9: er moet dan een optie worden geselecteerd waarvan het attribuut [value] de waarde van de eigenschap [DropDownListField] heeft. Hiervoor moet deze optie het attribuut [selected="selected"] hebben;
- regel 25: genereren van de tag <option value="valeur">libellé</option> met als waarde [@item.Value] en als label [@item.Label];
<!-- de lijst met één keuze -->
<tr>
<td>Liste à choix unique</td>
<td>
<select name="SimpleChoiceListField" size="3">
@{
foreach (ApplicationModel.Item item in @Model.SimpleChoiceListFieldItems)
{
string strChecked = item.Value == @Model.SimpleChoiceListField ? "selected=\"selected\"" : "";
<option value="@item.Value" @strChecked>@item.Label</option>
}
}
</select>
</tr>
De uitleg is dezelfde als voor de vervolgkeuzelijst.
<!-- de lijst met meerdere keuzemogelijkheden -->
<tr>
<td>Liste à choix multiple</td>
<td>
<select name="MultipleChoiceListField" size="3" multiple="multiple">
@{
foreach (ApplicationModel.Item item in @Model.MultipleChoiceListFieldItems)
{
string strChecked = @Model.MultipleChoiceListField.Contains(item.Value) ? "selected=\"selected\"" : "";
<option value="@item.Value" @strChecked>@item.Label</option>
}
}
</select>
</tr>
- regel 7: de verzameling die door de lijst wordt weergegeven, wordt doorlopen;
- regel 9: er moet een optie worden geselecteerd waarvan het attribuut [value] een van de waarden van de eigenschap [MultipleChoiceListField] heeft. Hiervoor moet de optie het attribuut [selected="selected"] hebben. We gebruiken een uitdrukking LINQ waarmee kan worden vastgesteld of een waarde in een array voorkomt;
- regel 10: genereren van de tag libellé</option met als waarde [@item.Value] en als label [@item.Label];
5.6.5. Verwerking van POST uit het formulier
We hebben gezien dat het formulier naar de actie [Action08Post] zou worden verzonden:
<form method="post" action="Action08Post">
De actie [Action08Post] is als volgt:
// Actie08-POST
[HttpPost]
public ViewResult Action08Post(ApplicationModel application, FormCollection posted)
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
ViewModel08 modèle = new ViewModel08(application);
TryUpdateModel(modèle,posted);
return View("Formulaire", modèle);
}
- regel 3: het applicatiesjabloon is een parameter, evenals de verzonden waarden. Deze zijn beschikbaar in een type [FormCollection]. De waarde van de verzonden parameter [RadioButtonField] wordt verkregen via de uitdrukking posted[" RadioButtonField"]. Dit levert een tekenreeks op of de pointer null. Als we posted[" CheckBoxesField"] schrijven, krijgen we een array van tekenreeksen of de pointer null;
- waarom schrijven we dan niet:
public ViewResult Action08Post(ApplicationModel application, ViewModel08 posted)
Daar zijn twee redenen voor:
- de eerste is dat het framework het model [ViewModel08] zal instantiëren met de constructor zonder parameters, waardoor de collecties van het model niet worden geïnitialiseerd;
- de tweede is dat we willen bepalen wat er in het model terechtkomt. We weten dat er vier mogelijke bronnen voor het model zijn: de parameters van een GET, van een POST, van de gebruikte route en die van een uploadé-bestand. Hier willen we het model uitsluitend initialiseren met de verzonden waarden.
- regel 6: we maken een instantie van het model met behulp van de juiste constructor;
- regel 7: we initialiseren het model met de verzonden waarden. Na deze bewerking komt het model overeen met de invoer die door de gebruiker is gedaan;
- regel 8: het formulier wordt opnieuw weergegeven. De gebruiker ziet het formulier terug zoals het is ingevuld.
Laten we een voorbeeld bekijken:
![]() |
In [2] komt het resultaat van [POST] goed overeen met wat er in [1] is ingevoerd.
5.6.6. Afhandeling van afwijkingen in POST
We hebben gezegd dat als er geen waarde was aangevinkt of geselecteerd voor de velden in [CheckBoxesField, SimpleChoiceListField, MultipleChoiceListField], de bijbehorende parameters geen deel uitmaakten van de verzonden string en dat de eigenschappen met dezelfde namen in het model dus niet werden geïnitialiseerd.
Laten we het volgende voorbeeld eens bekijken:
![]() |
- in [1] is geen enkel selectievakje aangevinkt;
- in [2] geeft [POST] een aangevinkt selectievakje weer.
De verklaring hiervoor is als volgt:
- omdat er geen enkel vakje is aangevinkt, maakt de parameter [CheckBoxesField] geen deel uit van de verzonden waarden;
- de actie [Action08Post] werkt als volgt:
[HttpPost]
public ViewResult Action08Post(ApplicationModel application, FormCollection posted)
{
ViewBag.info = ...
ViewModel08 modèle = new ViewModel08(application);
TryUpdateModel(modèle,posted);
return View("Formulaire", modèle);
}
- regel 5: het formuliersjabloon wordt geïnstantieerd. De gebruikte constructor wijst de array ["2"] toe aan de eigenschap [CheckBoxesField];
- regel 6: de verzonden waarden worden in het sjabloon opgeslagen. Aangezien de parameter [CheckBoxesField] geen deel uitmaakt van de verzonden waarden, wordt de eigenschap met dezelfde naam niet toegewezen. Deze behoudt dus de waarde ["2"], waardoor bij de weergave vakje nr. 2 is aangevinkt terwijl dat niet zou moeten.
Dit probleem kan op verschillende manieren worden opgelost. We kiezen ervoor om het op te lossen in de code van de actie [Action08Post]:
// Actie08-POST
[HttpPost]
public ViewResult Action08Post(ApplicationModel application, FormCollection posted)
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
ViewModel08 modèle = new ViewModel08(application);
TryUpdateModel(modèle,posted);
// verwerking van niet-verzonden waarden
if (posted["CheckBoxesField"] == null)
{
modèle.CheckBoxesField = new string[] { };
}
if (posted["SimpleChoiceListField"] == null)
{
modèle.SimpleChoiceListField = "";
}
if (posted["MultipleChoiceListField"] == null)
{
modèle.MultipleChoiceListField = new string[] { };
}
// formulier weergeven
return View("Formulaire", modèle);
}
- regels 9-20: er wordt gecontroleerd of bepaalde parameters al dan niet zijn verzonden. Als dat niet het geval is, worden ze geïnitialiseerd met de waarde die overeenkomt met het ontbreken van een invoer door de gebruiker. De controle is niet uitgevoerd voor de vervolgkeuzelijst, waarin altijd een item is geselecteerd, wat niet het geval is voor de andere lijsten.
De lezer wordt uitgenodigd om deze nieuwe versie te testen.
5.7. Gebruik van methoden die gespecialiseerd zijn in het genereren van formulieren
5.7.1. Het nieuwe formulier
We maken een nieuw formulier [Formulaire2.cshtml] aan dat een formulier oplevert dat identiek is aan het vorige:
![]() |
Laten we nog eens kijken naar de code die wordt gebruikt om de vervolgkeuzelijst van het formulier te genereren:
<!-- de vervolgkeuzelijst -->
<tr>
<td>Liste déroulante</td>
<td>
<select name="DropDownListField">
@{
foreach (ApplicationModel.Item item in @Model.DropDownListFieldItems)
{
string strChecked = item.Value == @Model.DropDownListField ? "selected=\"selected\"" : "";
<option value="@item.Value" @strChecked>@item.Label</option>
}
}
</select>
</tr>
Deze code heeft twee nadelen:
- het belangrijkste is dat we door de complexiteit van de code uit het oog verliezen wat voor soort component het is, in dit geval een keuzelijst;
- regel 5: als je je vergist in de naam van de eigenschap van het model die als attribuut [name] moet worden gebruikt, merk je dat pas tijdens de uitvoering.
ASP.NET MVC biedt gespecialiseerde methoden, genaamd [HTML Helpers], die, zoals de naam al aangeeft, bedoeld zijn om het genereren van de HTML te vergemakkelijken, met name voor formulieren. Met deze klassen wordt de eerdere keuzelijst als volgt geschreven:
<!-- de vervolgkeuzelijst -->
<tr>
<td>Liste déroulante</td>
<td>@Html.DropDownListFor(m => m.DropDownListField,
new SelectList(@Model.DropDownListFieldItems, "Value", "Label"))
</td>
</tr>
De keuzelijst wordt gegenereerd door de regels 4-5. De code is aanzienlijk minder complex. De voor de keuzelijst gegenereerde HTML-code is als volgt:
<!-- de vervolgkeuzelijst -->
<tr>
<td>Liste déroulante</td>
<td><select id="DropDownListField" name="DropDownListField"><option value="1">choix1</option>
<option selected="selected" value="2">choix2</option>
<option value="3">choix3</option>
</select></td>
</tr>
- regel 4: het attribuut [name] is correct;
- regels 4-6: de opties zijn correct gegenereerd en de juiste optie is geselecteerd.
Laten we teruggaan naar de code die deze regels HTML heeft gegenereerd:
@Html.DropDownListFor(m => m.DropDownListField, new SelectList(@Model.DropDownListFieldItems, "Value", "Label"))
- de eerste parameter is een functie lambda (dat is de naam ervan) waarbij m het model van de weergave vertegenwoordigt en m.DropDowListField een eigenschap van dit model is. De codegenerator HTML gebruikt de naam van deze eigenschap om de attributen [id] en [name] te genereren voor het [select] dat zal worden gegenereerd. Als er een niet-bestaande eigenschap wordt gebruikt, treedt er een fout op tijdens het compileren en niet meer tijdens de uitvoering. Dit is een verbetering ten opzichte van de vorige oplossing, waarbij fouten in de naamgeving pas tijdens de uitvoering werden gedetecteerd;
- de tweede parameter dient om de verzameling elementen aan te duiden die de vervolgkeuzelijst zal vullen. Met de klasse [SelectList] kan deze verzameling worden samengesteld:
- de eerste parameter is een willekeurige verzameling elementen. Hier hebben we een verzameling van het type [Item];
- de tweede parameter is de eigenschap van de elementen die de waarde van de tag <option> zal leveren. Hier is dat de eigenschap [Value] van de klasse [Item];
- de derde parameter is de eigenschap van de elementen die de tekst van de tag <option> zal leveren. Hier is dat de eigenschap [Label] van de klasse [Item];
- om te bepalen welke optie moet worden geselecteerd (attribuut selected), doet het framework hetzelfde als wij: het vergelijkt de waarde van de optie met de huidige waarde van de eigenschap [DropDownListField].
Laten we nu eens kijken naar de andere methoden die we kunnen gebruiken:
Keuzerondjes
De nieuwe code is als volgt:
<!-- de keuzerondjes -->
<tr>
<td>Etes-vous marié(e)</td>
<td>
@{
foreach (ApplicationModel.Item item in @Model.RadioButtonFieldItems)
{
@Html.RadioButtonFor(m => m.RadioButtonField, @item.Value)@item.Label
<text/>
}
}
</td>
</tr>
De gegenereerde code HTML is als volgt:
<!-- de keuzerondjes -->
<tr>
<td>Etes-vous marié(e)</td>
<td>
<input id="RadioButtonField" name="RadioButtonField" type="radio" value="1" />oui
<input checked="checked" id="RadioButtonField" name="RadioButtonField" type="radio" value="2" />non
</td>
</tr>
De gebruikte methode is [Html.RadioButtonFor]:
- de eerste parameter is de eigenschap van het model die aan de keuzeknop wordt gekoppeld (attribuut [name]);
- de tweede parameter is de waarde die aan de keuzeknop moet worden toegewezen (attribuut [value]).
Selectievakjes
De code verandert als volgt:
<!-- de selectievakjes -->
<tr>
<td>Cases à cocher</td>
<td>
@{
@Html.CheckBoxFor(m=>m.CheckBoxField1) @Model.CheckBoxesFieldItems[0].Label
@Html.CheckBoxFor(m=>m.CheckBoxField2) @Model.CheckBoxesFieldItems[1].Label
@Html.CheckBoxFor(m=>m.CheckBoxField3) @Model.CheckBoxesFieldItems[2].Label
}
</td>
De methode die wordt gebruikt om selectievakjes te genereren is [Html.CheckBoxFor]:
De parameter is de booleaanse eigenschap van het model die aan het selectievakje wordt gekoppeld. Als deze [Propriété=true] is, wordt het selectievakje aangevinkt. Als deze [Propriété=false] is, wordt het selectievakje niet aangevinkt. In beide gevallen is de waarde van het attribuut [value] gelijk aan true. De gegenereerde code HTML is als volgt:
<input id="Propriété" name="Propriété" type="checkbox" value="true" />
<input name="Propriété" type="hidden" value="false" />
- regel 1: het selectievakje met het attribuut [value="true"];
- regel 2: een verborgen veld (type=hidden) met dezelfde naam [Propriété] als het selectievakje met het attribuut [value="false"]. Waarom zijn er twee [input]-tags met dezelfde naam? Er zijn twee gevallen:
- het selectievakje op regel 1 is aangevinkt. Dan is de verzonden parameterreeks Eigenschap=true&Eigenschap=false (regels 1 en 2). Aangezien de eigenschap [Propriété] slechts één waarde verwacht, zou je kunnen denken dat het framework de waarde [true] toekent aan [Propriété]. Het zou volstaan om een logische OU te maken tussen de ontvangen waarden om dit te bereiken;
- het vakje op regel 1 is niet aangevinkt. De verzonden parameterreeks is dan Eigenschap=false (alleen regel 2) en de eigenschap [Propriété] krijgt de waarde [false], wat correct is (het vakje is niet aangevinkt).
Invoerveld met één regel
De nieuwe code is als volgt:
<!-- het tekstinvoerveld met één regel -->
<tr>
<td>Champ de saisie</td>
<td>
@Html.TextBoxFor(m => m.TextField, new { size = "30" })
</td>
</tr>
De gegenereerde code HTML is als volgt:
<!-- het tekstinvoerveld voor één regel -->
<tr>
<td>Champ de saisie</td>
<td>
<input id="TextField" name="TextField" size="30" type="text" value="quelques mots" />
</td>
</tr>
De gebruikte methode is als volgt:
@Html.TextBoxFor(m => m.TextField, new { size = "30" })
- de eerste parameter specificeert de eigenschap van het model dat aan het invoerveld is gekoppeld. De naam van de eigenschap wordt gebruikt in de attributen [name] en [id] van de gegenereerde tag <input> en de waarde ervan wordt toegewezen aan het attribuut [value];
- de tweede parameter is een anonieme klasse die bepaalde attributen van de gegenereerde tag HTML specificeert, in dit geval het attribuut [size].
Invoerveld voor een wachtwoord
De nieuwe code is als volgt:
<!-- het wachtwoordveld -->
<tr>
<td>Mot de passe</td>
<td>
@Html.PasswordFor(m => m.PasswordField, new { size = "15" })
</td>
</tr>
De gegenereerde code HTML is als volgt:
<!-- het wachtwoordinvoerveld -->
<tr>
<td>Mot de passe</td>
<td>
<input id="PasswordField" name="PasswordField" size="15" type="password" />
</td>
</tr>
De gebruikte methode is als volgt:
@Html.PasswordFor(m => m.PasswordField, new { size = "15" })
De werking is vergelijkbaar met die van de methode [Html.TexBoxFor].
Invoerveld met meerdere regels
De nieuwe code is als volgt:
<!-- het tekstinvoerveld voor meerdere regels -->
<tr>
<td>Boîte de saisie</td>
<td>
@Html.TextAreaFor(m => m.TextAreaField, new { cols = "30", rows = "5" })
</td>
</tr>
De gegenereerde code HTML is als volgt:
<!-- het tekstinvoerveld voor meerdere regels -->
<tr>
<td>Boîte de saisie</td>
<td>
<textarea cols="30" id="TextAreaField" name="TextAreaField" rows="5">
ligne1
ligne2</textarea>
</td>
</tr>
De gebruikte methode is als volgt:
@Html.TextAreaFor(m => m.TextAreaField, new { cols = "30", rows = "5" })
De werking is vergelijkbaar met die van de methode [Html.TexBoxFor].
Keuzelijst met één optie
De nieuwe code is als volgt:
<!-- de keuzelijst met één optie -->
<tr>
<td>Liste à choix unique</td>
<td>
@Html.DropDownListFor(m => m.SimpleChoiceListField, new SelectList(@Model.SimpleChoiceListFieldItems, "Value", "Label"), new { size = "3" })
</tr>
en de gegenereerde code HTML is als volgt:
<!-- de lijst met één keuze -->
<tr>
<td>Liste à choix unique</td>
<td>
<select id="SimpleChoiceListField" name="SimpleChoiceListField" size="3">
<option value="1">liste1</option>
<option value="2">liste2</option>
<option selected="selected" value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</tr>
We hebben de methode [Html.DropDownListFor] al besproken. Het enige verschil is hier de derde parameter, die wordt gebruikt om een [size]-attribuut te specificeren dat anders is dan 1. Dit kenmerk zorgt ervoor dat de lijst verandert van een vervolgkeuzelijst ([size=1]) naar een eenvoudige lijst.
De keuzelijst
De nieuwe code is als volgt:
<!-- de lijst met meerdere keuzemogelijkheden -->
<tr>
<td>Liste à choix multiple</td>
<td>
@Html.ListBoxFor(m => m.MultipleChoiceListField, new SelectList(@Model.MultipleChoiceListFieldItems, "Value", "Label"), new { size = "5" })
</tr>
en de gegenereerde code HTML is als volgt:
<!-- de lijst met meerdere keuzemogelijkheden -->
<tr>
<td>Liste à choix multiple</td>
<td>
<select id="MultipleChoiceListField" multiple="multiple" name="MultipleChoiceListField" size="5">
<option selected="selected" value="1">liste1</option>
<option value="2">liste2</option>
<option selected="selected" value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</tr>
De methode
@Html.ListBoxFor(m => m.MultipleChoiceListField, new SelectList(@Model.MultipleChoiceListFieldItems, "Value", "Label"), new { size = "5" })
werkt net als de methode [Html.DropDownListFor], behalve dat deze een lijst met meerdere selectiemogelijkheden genereert. De geselecteerde opties zijn die waarvan de waarde (attribuut value) in de tabel [MultipleChoiceListField] staat.
De tag <form> kan ook met een methode worden gegenereerd:
@using (Html.BeginForm("Action09Post", "First"))
{
...
}
De gegenereerde code HTML is als volgt:
<form action="/First/Action09Post" method="post">
...
</form>
De methode
Html.BeginForm("Action09Post", "First")
heeft als eerste parameter de naam van een actie en als tweede parameter de naam van een controller.
5.7.2. De acties en het model
Het formulier wordt gegenereerd door de volgende actie [Action09Get]:
// Actie09-GET
[HttpGet]
public ViewResult Action09Get(ApplicationModel application)
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
return View("Formulaire2", new ViewModel09(application));
}
De weergave die in regel 6 wordt weergegeven, is [Formulaire2], gekoppeld aan het volgende model [ViewModel09]:
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Exemple_03.Models;
namespace Exemple_03.Models
{
public class ViewModel09
{
// de invoervelden
public string RadioButtonField { get; set; }
public bool CheckBoxField1 { get; set; }
public bool CheckBoxField2 { get; set; }
public bool CheckBoxField3 { get; set; }
public string TextField { get; set; }
public string PasswordField { get; set; }
public string TextAreaField { get; set; }
public string DropDownListField { get; set; }
public string SimpleChoiceListField { get; set; }
public string[] MultipleChoiceListField { get; set; }
// de collecties die in het formulier moeten worden weergegeven
public ApplicationModel.Item[] RadioButtonFieldItems { get; set; }
public ApplicationModel.Item[] CheckBoxesFieldItems { get; set; }
public ApplicationModel.Item[] DropDownListFieldItems { get; set; }
public ApplicationModel.Item[] SimpleChoiceListFieldItems { get; set; }
public ApplicationModel.Item[] MultipleChoiceListFieldItems { get; set; }
// constructors
public ViewModel09()
{
}
public ViewModel09(ApplicationModel application)
{
// initialisatie van collecties
RadioButtonFieldItems = application.RadioButtonFieldItems;
CheckBoxesFieldItems = application.CheckBoxesFieldItems;
DropDownListFieldItems = application.DropDownListFieldItems;
SimpleChoiceListFieldItems = application.SimpleChoiceListFieldItems;
MultipleChoiceListFieldItems = application.MultipleChoiceListFieldItems;
// initialisatie velden
RadioButtonField = "2";
CheckBoxField2 = true;
TextField = "quelques mots";
PasswordField = "secret";
TextAreaField = "ligne1\nligne2";
DropDownListField = "2";
SimpleChoiceListField = "3";
MultipleChoiceListField = new string[] { "1", "3" };
}
}
}
[ViewModel09] verschilt van [ViewModel08] door de manier waarop de selectievakjes worden afgehandeld. In plaats van een tabel met drie selectievakjes zijn drie afzonderlijke selectievakjes gebruikt (regels 11-13).
Het formulier wordt verwerkt door de volgende actie [Action09Post]:
// Actie09-POST
[HttpPost]
public ViewResult Action09Post(ApplicationModel application, FormCollection posted)
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
ViewModel09 modèle = new ViewModel09(application);
TryUpdateModel(modèle, posted);
// verwerking van niet-verzonden waarden
if (posted["SimpleChoiceListField"] == null)
{
modèle.SimpleChoiceListField = "";
}
if (posted["MultipleChoiceListField"] == null)
{
modèle.MultipleChoiceListField = new string[] { };
}
// formulier weergeven
return View("Formulaire2", modèle);
}
De actie [Action09Post] is identiek aan de actie [Action08Post], op twee punten na:
- regel 18: de weergave [Formulaire2] wordt gebruikt in plaats van de weergave [Formulaire];
- de afhandeling van de selectievakjes die niet zijn aangevinkt, is verwijderd. Dit wordt nu correct afgehandeld door de methode [Html.CheckBoxFor].
5.8. Een formulier genereren op basis van de metagegevens van het model
Er bestaan naast de eerder genoemde methoden nog andere manieren om een formulier te genereren. Een daarvan bestaat erin informatie aan een veld van het model te koppelen, waardoor het framework MVC weet welke invoertag het moet genereren. Deze informatie wordt metadata genoemd.
Laten we eens kijken naar het volgende weergavemodel [ViewModel10]:
![]() |
using System;
using System.ComponentModel.DataAnnotations;
using System.Drawing;
namespace Exemple_03.Models
{
public class ViewModel10
{
[Display(Name="Text")]
[DataType(DataType.Text)]
public string Text { get; set; }
[Display(Name = "TextArea")]
[DataType(DataType.MultilineText)]
public string MultiLineText { get; set; }
[Display(Name = "Number")]
public int Number { get; set; }
[Display(Name = "Decimal")]
[UIHint("Decimal")]
public double Decimal { get; set; }
[Display(Name = "Tel")]
[DataType(DataType.PhoneNumber)]
public string Tel { get; set; }
[Display(Name = "Date")]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[Display(Name = "Time")]
[DataType(DataType.Time)]
public DateTime Time { get; set; }
[Display(Name = "HiddenInput")]
[UIHint("HiddenInput")]
public string HiddenInput { get; set; }
[Display(Name = "Boolean")]
[UIHint("Boolean")]
public bool Boolean { get; set; }
[Display(Name = "Email")]
[DataType(DataType.EmailAddress)]
public string Email{ get; set; }
[Display(Name = "Url")]
[DataType(DataType.Url)]
public string Url { get; set; }
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Currency")]
[DataType(DataType.Currency)]
public double Currency { get; set; }
[Display(Name = "CreditCard")]
[DataType(DataType.CreditCard)]
public string CreditCard { get; set; }
// constructor
public ViewModel10()
{
Text = "tra la la";
MultiLineText = "ligne1\nligne2";
Number = 4;
Decimal = 10.2;
Tel = "0617181920";
Date = DateTime.Now;
Time = DateTime.Now;
HiddenInput = "caché";
Boolean = true;
Email = "x@y.z";
Url = "http://istia.univ-angers.fr";
Password = "mdp";
Currency = 4.2;
CreditCard = "0123456789012345";
}
}
}
De metadata bestaat uit de tags [Display, DataType, UIHint].
Dit weergavemodel wordt opgebouwd door de volgende actie [Action10Get]:
// Actie10-GET
[HttpGet]
public ViewResult Action10Get()
{
return View(new ViewModel10());
}
In regel 5 hierboven wordt de standaardweergave van de actie [/First/Action10Get.cshtml ] gevraagd om het weergavesjabloon van het type [ViewModel10] weer te geven. Deze weergave is als volgt:
![]() |
@model Exemple_03.Models.ViewModel10
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action10Get</title>
</head>
<body>
<h3>Formulaire ASP.NET MVC - 2</h3>
@using (Html.BeginForm("Action10Post", "First"))
{
<table>
<thead>
<tr>
<th>LabelFor</th>
<th>EditorFor</th>
<th>DisplayFor</th>
</tr>
</thead>
<tbody>
<tr>
<td>@Html.LabelFor(m => m.Text)</td>
<td>@Html.EditorFor(m => m.Text)</td>
<td>@Html.DisplayFor(m => m.Text)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.MultiLineText)</td>
<td>@Html.EditorFor(m => m.MultiLineText)</td>
<td>@Html.DisplayFor(m => m.MultiLineText)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Number)</td>
<td>@Html.EditorFor(m => m.Number)</td>
<td>@Html.DisplayFor(m => m.Number)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Decimal)</td>
<td>@Html.EditorFor(m => m.Decimal)</td>
<td>@Html.DisplayFor(m => m.Decimal)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Tel)</td>
<td>@Html.EditorFor(m => m.Tel)</td>
<td>@Html.DisplayFor(m => m.Tel)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Date)</td>
<td>@Html.EditorFor(m => m.Date)</td>
<td>@Html.DisplayFor(m => m.Date)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Time)</td>
<td>@Html.EditorFor(m => m.Time)</td>
<td>@Html.DisplayFor(m => m.Time)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.HiddenInput)</td>
<td>@Html.EditorFor(m => m.HiddenInput)</td>
<td>@Html.DisplayFor(m => m.HiddenInput)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Boolean)</td>
<td>@Html.EditorFor(m => m.Boolean)</td>
<td>@Html.DisplayFor(m => m.Boolean)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Email)</td>
<td>@Html.EditorFor(m => m.Email)</td>
<td>@Html.DisplayFor(m => m.Email)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Url)</td>
<td>@Html.EditorFor(m => m.Url)</td>
<td>@Html.DisplayFor(m => m.Url)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Password)</td>
<td>@Html.EditorFor(m => m.Password)</td>
<td>@Html.DisplayFor(m => m.Password)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Currency)</td>
<td>@Html.EditorFor(m => m.Currency)</td>
<td>@Html.DisplayFor(m => m.Currency)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.CreditCard)</td>
<td>@Html.EditorFor(m => m.CreditCard)</td>
<td>@Html.DisplayFor(m => m.CreditCard)</td>
</tr>
</tbody>
</table>
<input type="submit" value="Valider" />
}
</body>
</html>
Voor elk van de eigenschappen van het model gebruiken we de methode:
- Html.LabelFor om de waarde van de metagegevens [DisplayName] van de eigenschap weer te geven;
- Html.EditorFor om de tag HTML te genereren voor het invoeren van de waarde van de eigenschap. Deze methode maakt gebruik van de metagegevens [DataType] en [UIHint] van de eigenschap;
- Html.DisplayFor om de waarde van de eigenschap weer te geven volgens het formaat dat is aangegeven door de metadata [DataType].
Hier volgt een voorbeeld van de uitvoering in de Chrome-browser:

Afhankelijk van de gebruikte browser kunnen de pagina’s er anders uitzien. De gegenereerde weergave maakt namelijk gebruik van de nieuwe tags die zijn geïntroduceerd in versie 5 van HTML, ook wel HTML5 genoemd. Niet alle browsers ondersteunen deze versie nog. Hierboven is te zien dat de Chrome-browser deze versie gedeeltelijk ondersteunt.
5.8.1. De [POST] van het formulier
De [POST] van het formulier wordt verwerkt door de volgende actie [Action10Post]:
// Actie10-POST
[HttpPost]
public ContentResult Action10Post(ViewModel10 modèle)
{
string erreurs = getErrorMessagesFor(ModelState);
string texte = string.Format("Contrôleur={0}, Action={1}, valide={2}, erreurs={3}", RouteData.Values["controller"], RouteData.Values["action"], ModelState.IsValid, erreurs);
return Content(texte, "text/plain", Encoding.UTF8);
}
- regel 3: de actie [Action10Post] heeft het verzonden formulier als invoermodel;
- regel 5: de validatiefouten van dit formulier worden opgehaald;
- regel 6: het tekstantwoord aan de klant wordt opgesteld;
- regel 7: dit wordt verzonden.
Laten we nu de eigenschappen van het model [ViewModel10] één voor één bekijken en zien hoe de bijbehorende metagegevens invloed hebben op het gegenereerde HTML en de validatie van de invoervelden.
5.8.2. Eigenschap [Text]
Definitie
[Display(Name="Text")]
[DataType(DataType.Text)]
public string Text { get; set; }
...
Text = "tra la la";
Weergave
<tr>
<td>@Html.LabelFor(m => m.Text)</td>
<td>@Html.EditorFor(m => m.Text)</td>
<td>@Html.DisplayFor(m => m.Text)</td>
</tr>
Afbeelding
![]() |
HTML gegenereerd
<tr>
<td><label for="Text">Text</label></td>
<td><input class="text-box single-line" id="Text" name="Text" type="text" value="tra la la" /></td>
<td>tra la la</td>
</tr>
Opmerkingen
- de methode [Html.LabelFor] heeft de tag <label> van regel 2 gegenereerd. De waarde van het attribuut [for] is de naam van de parameter van de methode [Html.LabelFor]
public string Text { get; set; }
De tekst die tussen het begin en het einde van de tag wordt weergegeven, is de tekst van de metagegevens
[Display(Name="Text")]
De methode [Html.LabelFor] gaat altijd op deze manier te werk. We zullen hier bij de andere eigenschappen niet op terugkomen.
- De methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd. Merk op dat deze een attribuut [class] heeft dat de klasse CSS [text-box single-line] aan de tag koppelt. De attributen [id] en [name] hebben als waarde de naam [Text] van de eigenschap ‘parameter’ van de methode [Html.EditorFor]. Het attribuut [type] heeft de waarde [text] gekregen vanwege de metagegevens
[DataType(DataType.Text)]
- de methode [Html.DisplayFor] heeft de tekst van regel 4 gegenereerd. Dit is de waarde van de parameter-eigenschap van de methode [Html.DisplayFor ]. Deze methode wordt beïnvloed door de metagegevens
[DataType(DataType.Text)]
waardoor de waarde als onopgemaakte tekst wordt weergegeven.
5.8.3. Eigenschap [MultiLineText]
Definitie
[Display(Name = "TextArea")]
[DataType(DataType.MultilineText)]
public string MultiLineText { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.MultiLineText)</td>
<td>@Html.EditorFor(m => m.MultiLineText)</td>
<td>@Html.DisplayFor(m => m.MultiLineText)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="MultiLineText">TextArea</label></td>
<td><textarea class="text-box multi-line" id="MultiLineText" name="MultiLineText">
ligne1
ligne2</textarea></td>
<td>ligne1
ligne2</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <textarea> van regel 3 gegenereerd. Merk op dat deze een attribuut [class] heeft dat de klasse CSS [text-box multi-line] aan de tag koppelt. De attributen [id] en [name] hebben als waarde de naam [MultiLineText] van de eigenschap ‘parameter’ van de methode [Html.EditorFor]. Dit is altijd het geval. We zullen dit niet meer vermelden. De gegenereerde tag is <textarea> vanwege de metagegevens
[DataType(DataType.MultilineText)]
waarin werd gespecificeerd dat de eigenschap uit meerdere regels tekst bestond.
- De methode [Html.DisplayFor] heeft de tekst van de regels 4-5 gegenereerd. Dit is de waarde van de parameter-eigenschap van de methode [Html.DisplayFor ].
5.8.4. Eigenschap [Number]
Definitie
[Display(Name = "Number")]
public int Number { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Number)</td>
<td>@Html.EditorFor(m => m.Number)</td>
<td>@Html.DisplayFor(m => m.Number)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Number">Number</label></td>
<td><input class="text-box single-line" data-val="true" data-val-number="Le champ Number doit être un nombre." data-val-required="Le champ Number est requis." id="Number" name="Number" type="number" value="4" /></td>
<td>4</td>
</tr>
Opmerkingen
- De methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [number]. Blijkbaar simpelweg omdat de eigenschap het type [int] heeft. De attributen [data-val], [data-val-number] en [data-val-required] worden niet herkend door HTML5. Ze worden gebruikt door een JavaScript-framework voor client-side gegevensvalidatie;
- de methode [Html.DisplayFor] heeft de tekst op regel 4 gegenereerd, de waarde van de eigenschap.
Validatie
De attributen [data-x] beïnvloeden de validatie van gegevens aan de clientzijde. Hier volgen twee voorbeelden:
We voeren een onjuist getal in en valideren:
![]() |
Hierboven vond de validatie aan de clientzijde plaats. Het formulier wordt pas verzonden zodra de fout is gecorrigeerd.
Een ander voorbeeld: er wordt niets ingevoerd:
![]() |
In het bovenstaande voorbeeld [1] geeft [Action10Post] een foutmelding. Misschien herinner je je nog dat we dit gedrag al hadden verkregen door het attribuut [Required] te gebruiken op de te controleren eigenschap (zie pagina 69), in dit geval de eigenschap [Number]. Hier hoefden we dat niet te doen.
5.8.5. Eigenschap [Decimal]
Definitie
[Display(Name = "Decimal")]
[UIHint("Decimal")]
public double Decimal { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Decimal)</td>
<td>@Html.EditorFor(m => m.Decimal)</td>
<td>@Html.DisplayFor(m => m.Decimal)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Decimal">Decimal</label></td>
<td><input class="text-box single-line" data-val="true" data-val-number="Le champ Decimal doit être un nombre." data-val-required="Le champ Decimal est requis." id="Decimal" name="Decimal" type="text" value="10,20" /></td>
<td>10,20</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [text]. De overige attributen zijn identiek aan die welke voor de vorige eigenschap [Number] zijn gegenereerd. De metagegevens:
[UIHint("Decimal")]
zorgt ervoor dat de waarde van de eigenschap met twee decimalen wordt weergegeven voor beide methoden [Html.EditorFor] en [Html.DisplayFor]
Validatie
Er wordt aan de clientzijde geen validatiefout gemeld, in tegenstelling tot het vorige geval. De fout wordt alleen gemeld door de actie [Action10Post]. Ook hier is het decimale getal vereist zonder dat het attribuut [Required] hoeft te worden ingesteld.
5.8.6. Eigenschap [Tel]
Definitie
[Display(Name = "Tel")]
[DataType(DataType.PhoneNumber)]
public string Tel { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Tel)</td>
<td>@Html.EditorFor(m => m.Tel)</td>
<td>@Html.DisplayFor(m => m.Tel)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Tel">Tel</label></td>
<td><input class="text-box single-line" id="Tel" name="Tel" type="tel" value="0617181920" /></td>
<td>0617181920</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [tel]. Deze waarde is gegenereerd op basis van de metagegevens:
[DataType(DataType.PhoneNumber)]
Het type [tel] voor een <input>-tag is een nieuw type ten opzichte van HTML5. De Chrome-browser heeft deze tag verwerkt als een <input>-tag met het type [text].
Validatie
Er worden geen validatiefouten gemeld, noch aan de clientzijde, noch aan de serverzijde. Er kan willekeurig iets worden ingevoerd.
5.8.7. Eigenschap [Date]
Definitie
[Display(Name = "Date")]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Date)</td>
<td>@Html.EditorFor(m => m.Date)</td>
<td>@Html.DisplayFor(m => m.Date)</td>
</tr>
Afbeelding
![]() |
HTML gegenereerd
<tr>
<td><label for="Date">Date</label></td>
<td><input class="text-box single-line" data-val="true" data-val-date="Le champ Date doit être une date." data-val-required="Le champ Date est requis." id="Date" name="Date" type="date" value="11/10/2013" /></td>
<td>11/10/2013</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [date]. Deze waarde is gegenereerd op basis van de metagegevens:
[DataType(DataType.Date)]
Het type [date] voor een <input>-tag is een nieuw type HTML5. De Chrome-browser herkent dit en maakt het mogelijk om de datum via een kalender in te voeren. Bovendien wordt de ingevoerde datum weergegeven in het formaat [jj/mm/aaaa], d.w.z. dat Chrome het datumformaat aanpast aan het [locale] van de browser.
- Ook de methode [Html.DisplayFor] schreef de datum in de vorm [jj/mm/aaaa], eveneens vanwege de aanwezigheid van de metagegevens [Date].
Validatie
Er wordt aan de clientzijde een ongeldige datum gemeld ([1]), waardoor de verzending van het formulier (POST) naar de server wordt verhinderd.
![]() |
Het ontbreken van een datum wordt niet gemeld aan de clientzijde, maar wel aan de serverzijde: [2].
5.8.8. Eigenschap [Time]
Definitie
[Display(Name = "Time")]
[DataType(DataType.Time)]
public DateTime Time { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Time)</td>
<td>@Html.EditorFor(m => m.Time)</td>
<td>@Html.DisplayFor(m => m.Time)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Time">Time</label></td>
<td><input class="text-box single-line" data-val="true" data-val-required="Le champ Time est requis." id="Time" name="Time" type="time" value="11:17" /></td>
<td>11:17</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [time]. Deze waarde is gegenereerd op basis van de metagegevens:
[DataType(DataType.Time)]
Het type [time] voor een <input>-tag is een nieuw type HTML5. De Chrome-browser herkent dit en maakt het mogelijk om een tijd in te voeren in de vorm [hh:mm];
- de methode [Html.DisplayFor] schreef de tijd eveneens in de vorm [hh:mm], nog steeds vanwege de aanwezigheid van de metadata [Time].
Validatie
Het is technisch niet mogelijk om een ongeldige tijd in te voeren. Het ontbreken van een tijd wordt aan de serverzijde gemeld:
![]() |
5.8.9. Eigenschap [HiddenInput]
Definitie
[Display(Name = "HiddenInput")]
[UIHint("HiddenInput")]
public string HiddenInput { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.HiddenInput)</td>
<td>@Html.EditorFor(m => m.HiddenInput)</td>
<td>@Html.DisplayFor(m => m.HiddenInput)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="HiddenInput">HiddenInput</label></td>
<td>caché<input id="HiddenInput" name="HiddenInput" type="hidden" value="verborgen" /></td>
<td>caché</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [hidden], d.w.z. een verborgen (maar niettemin verzonden) veld. Deze waarde is gegenereerd op basis van de metagegevens:
[UIHint("HiddenInput")]
- De methode [Html.DisplayFor] heeft zelf de waarde van het verborgen veld geschreven.
5.8.10. Eigenschap [Boolean]
Definitie
[Display(Name = "Boolean")]
public bool Boolean { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Boolean)</td>
<td>@Html.EditorFor(m => m.Boolean)</td>
<td>@Html.DisplayFor(m => m.Boolean)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Boolean">Boolean</label></td>
<td><input checked="checked" class="check-box" data-val="true" data-val-required="Le champ Boolean est requis." id="Boolean" name="Boolean" type="checkbox" value="true" /><input name="Boolean" type="hidden" value="false" /></td>
<td><input checked="checked" class="check-box" disabled="disabled" type="checkbox" /></td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [checkbox], d.w.z. een selectievakje. Deze waarde is gegenereerd omdat de eigenschap booleaans is:
public bool Boolean { get; set; }
- de methode [Html.DisplayFor] heeft regel 4 gegenereerd, eveneens een selectievakje (attribuut type) maar uitgeschakeld (attribuut disabled).
5.8.11. Eigenschap [Email]
Definitie
[Display(Name = "Email")]
[DataType(DataType.EmailAddress)]
public string Email{ get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Email)</td>
<td>@Html.EditorFor(m => m.Email)</td>
<td>@Html.DisplayFor(m => m.Email)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Email">Email</label></td>
<td><input class="text-box single-line" id="Email" name="Email" type="email" value="x@y.z" /></td>
<td><a href="mailto:x@y.z">x@y.z</a></td>
</tr>
Opmerkingen
- De methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [email]. Dit type is nieuw in HTML5. Dit type is gegenereerd op basis van de metagegevens:
[DataType(DataType.EmailAddress)]
Chrome lijkt dit type te hebben behandeld als een type [text].
- De methode [Html.DisplayFor] heeft regel 4 gegenereerd: een link naar het e-mailadres.
Validatie
Er wordt aan de clientzijde een ongeldig adres gemeld: [1]:
![]() |
Het ontbreken van een invoer leidt niet tot een fout.
5.8.12. Eigenschap [Url]
Definitie
[Display(Name = "Url")]
[DataType(DataType.Url)]
public string Url { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Url)</td>
<td>@Html.EditorFor(m => m.Url)</td>
<td>@Html.DisplayFor(m => m.Url)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Url">Url</label></td>
<td><input class="text-box single-line" id="Url" name="Url" type="url" value="http://istia.univ-angers.fr" /></td>
<td><a href="http://istia.univ-angers.fr">http://istia.univ-angers.fr</a></td>
</tr>
Opmerkingen
- De methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [url]. Dit type is nieuw in HTML5. Het is gegenereerd op basis van de metagegevens:
[DataType(DataType.Url)]
Chrome lijkt dit type te behandelen als een type [text].
- De methode [Html.DisplayFor] heeft regel 4 gegenereerd: een link naar URL.
Validatie
Er wordt aan de clientzijde een ongeldige URL gemeld: [1]:
![]() |
Het ontbreken van een invoer leidt niet tot een fout.
5.8.13. Eigenschap [Password]
Definitie
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Password { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Password)</td>
<td>@Html.EditorFor(m => m.Password)</td>
<td>@Html.DisplayFor(m => m.Password)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Password">Password</label></td>
<td><input class="text-box single-line password" id="Password" name="Password" type="password" value="mdp" /></td>
<td>mdp</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [password]. Dit type is gegenereerd op basis van de metagegevens:
[DataType(DataType.Password)]
- de methode [Html.DisplayFor] heeft regel 4 gegenereerd.
5.8.14. Eigenschap [Currency]
Definitie
[Display(Name = "Currency")]
[DataType(DataType.Currency)]
public double Currency { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.Currency)</td>
<td>@Html.EditorFor(m => m.Currency)</td>
<td>@Html.DisplayFor(m => m.Currency)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="Currency">Currency</label></td>
<td><input class="text-box single-line" data-val="true" data-val-number="Le champ Currency doit être un nombre." data-val-required="Le champ Currency est requis." id="Currency" name="Currency" type="text" value="4,2" /></td>
<td>4,20 €</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [text];
- de methode [Html.DisplayFor] heeft regel 4 gegenereerd, een getal met twee decimalen en een valutasymbool. Dit formaat is gebruikt vanwege de metagegevens:
[DataType(DataType.Currency)]
Validatie
Een ongeldige waarde [1] of het ontbreken van een waarde [2] wordt aan de serverzijde gemeld:
![]() |
5.8.15. Object [CreditCard]
Definitie
[Display(Name = "CreditCard")]
[DataType(DataType.CreditCard)]
public string CreditCard { get; set; }
Weergave
<tr>
<td>@Html.LabelFor(m => m.CreditCard)</td>
<td>@Html.EditorFor(m => m.CreditCard)</td>
<td>@Html.DisplayFor(m => m.CreditCard)</td>
</tr>
Afbeelding
HTML gegenereerd
<tr>
<td><label for="CreditCard">CreditCard</label></td>
<td><input class="text-box single-line" id="CreditCard" name="CreditCard" type="text" value="0123456789012345" /></td>
<td>0123456789012345</td>
</tr>
Opmerkingen
- de methode [Html.EditorFor] heeft de tag <input> van regel 3 gegenereerd met een attribuut [type] van het type [text]. De methode [Html.DisplayFor] heeft regel 4 gegenereerd. Het is hier niet duidelijk wat de metagegevens toevoegen:
[DataType(DataType.CreditCard)]
Validatie
Er vindt geen controle plaats, noch aan de clientzijde, noch aan de serverzijde.
5.9. Validatie van een formulier
We zijn het probleem van de validatie van het model van een actie al tegengekomen in paragraaf 4.5 en de daaropvolgende paragrafen. We komen op deze kwestie terug in het kader van een formulier:
- hoe kunnen we invoerfouten aan de gebruiker melden;
- zowel aan de clientzijde als aan de serverzijde validaties uitvoeren om fouten sneller aan de gebruiker te melden.
5.9.1. Validatie aan de serverzijde
Laten we het volgende model eens bekijken:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Net.Mail;
namespace Exemple_03.Models
{
public class ViewModel11 : IValidatableObject
{
[Required(ErrorMessage = "Information requise")]
[Display(Name = "Chaîne d'au moins quatre caractères")]
[RegularExpression(@"^.{4,}$", ErrorMessage = "Information incorrecte")]
public string Chaine1 { get; set; }
[Display(Name = "Chaîne d'au plus quatre caractères")]
[Required(ErrorMessage = "Information requise")]
[RegularExpression(@"^.{1,4}$", ErrorMessage = "Information incorrecte")]
public string Chaine2 { get; set; }
[Required(ErrorMessage = "Information requise")]
[Display(Name = "Chaîne de quatre caractères exactement")]
[RegularExpression(@"^.{4,4}$", ErrorMessage = "Information incorrecte")]
public string Chaine3 { get; set; }
[Required(ErrorMessage = "Information requise")]
[Display(Name = "Nombre entier")]
public int Entier1 { get; set; }
[Display(Name = "Nombre entier dans l'intervalle [1,100]")]
[Required(ErrorMessage = "Information requise")]
[Range(1, 100, ErrorMessage = "Information incorrecte")]
public int Entier2 { get; set; }
[Display(Name = "Nombre réel")]
[Required(ErrorMessage = "Information requise")]
public double Reel1 { get; set; }
[Display(Name = "Nombre réel dans l'intervalle [10.2, 11.3]")]
[Required(ErrorMessage = "Information requise")]
[Range(10.2, 11.3, ErrorMessage = "Information incorrecte")]
public double Reel2 { get; set; }
[Display(Name = "Adresse mail")]
[Required(ErrorMessage = "Information requise")]
public string Email1 { get; set; }
[Display(Name = "Date sous la forme dd/jj/aaaa")]
[RegularExpression(@"\s*\d{2}/\d{2}/\d{4}\s*", ErrorMessage = "Information incorrecte")]
[Required(ErrorMessage = "Information requise")]
public string Regexp1 { get; set; }
[Display(Name = "Date postérieure à celle d'aujourd'hui")]
[Required(ErrorMessage = "Information requise")]
[DataType(DataType.Date)]
public DateTime Date1 { get; set; }
// validatie
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> résultats = new List<ValidationResult>();
// Datum 1
if (Date1.Date <= DateTime.Now.Date)
{
résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Date1" }));
}
// E-mail 1
try
{
new MailAddress(Email1);
}
catch
{
résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Email1" }));
}
// de lijst met fouten wordt weergegeven
return résultats;
}
}
}
Dit model wordt weergegeven door de volgende weergave [Action11Get.cshtml]:
![]() |
@model Exemple_03.Models.ViewModel11
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action11Get</title>
<link rel="stylesheet" href="~/Content/Site.css" />
</head>
<body>
<h3>Formulaire ASP.NET MVC – Validation 1</h3>
@using (Html.BeginForm("Action11Post", "First"))
{
<table>
<thead>
<tr>
<th>Type attendu</th>
<th>Valeur saisie</th>
<th>Message d'erreur</th>
</tr>
</thead>
<tbody>
<tr>
<td>@Html.LabelFor(m => m.Chaine1)</td>
<td>@Html.EditorFor(m => m.Chaine1)</td>
<td>@Html.ValidationMessageFor(m => m.Chaine1)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Chaine2)</td>
<td>@Html.EditorFor(m => m.Chaine2)</td>
<td>@Html.ValidationMessageFor(m => m.Chaine2)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Chaine3)</td>
<td>@Html.EditorFor(m => m.Chaine3)</td>
<td>@Html.ValidationMessageFor(m => m.Chaine3)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Entier1)</td>
<td>@Html.EditorFor(m => m.Entier1)</td>
<td>@Html.ValidationMessageFor(m => m.Entier1)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Entier2)</td>
<td>@Html.EditorFor(m => m.Entier2)</td>
<td>@Html.ValidationMessageFor(m => m.Entier2)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Reel1)</td>
<td>@Html.EditorFor(m => m.Reel1)</td>
<td>@Html.ValidationMessageFor(m => m.Reel1)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Reel2)</td>
<td>@Html.EditorFor(m => m.Reel2)</td>
<td>@Html.ValidationMessageFor(m => m.Reel2)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Email1)</td>
<td>@Html.EditorFor(m => m.Email1)</td>
<td>@Html.ValidationMessageFor(m => m.Email1)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Regexp1)</td>
<td>@Html.EditorFor(m => m.Regexp1)</td>
<td>@Html.ValidationMessageFor(m => m.Regexp1)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Date1)</td>
<td>@Html.EditorFor(m => m.Date1)</td>
<td>@Html.ValidationMessageFor(m => m.Date1)</td>
</tr>
</tbody>
</table>
<p>
<input type="submit" value="Valider" />
</p>
}
</body>
</html>
- regel 12: er wordt verwezen naar het stylesheet [Site.css]. Dit bevat standaard klassen die worden gebruikt om invoerfouten in het formulier te markeren;
- regels 18-25: een tabel met drie kolommen:
- kolom 1 geeft tekst weer met de methode [Html.LabelFor],
- kolom 2 geeft de invoer weer met de methode [Html.EditorFor],
- kolom 3 geeft eventuele invoerfouten weer met de methode [Html.ValidationMessageFor];
De actie [Action11Get] dient om het formulier weer te geven:
// Actie11-GET
[HttpGet]
public ViewResult Action11Get()
{
return View("Action11Get", new ViewModel11());
}
De actie [Action11Post] dient om het formulier opnieuw weer te geven met eventuele invoerfouten:
// Actie11-POST
[HttpPost]
public ViewResult Action11Post(ViewModel11 modèle)
{
return View("Action11Get", modèle);
}
- regel 3: het model [ViewModel11] wordt aangemaakt en vervolgens geïnitialiseerd met de verzonden waarden. Er kunnen dan fouten optreden. Aan elke foutieve eigenschap P van het model is een foutmelding gekoppeld. Deze foutmelding kan worden opgehaald met de methode [Html.ValidationMessageFor] van het formulier.
Hier volgt een uitvoervoorbeeld:
![]() | ![]() |
Hier is nog een voorbeeld:
![]() |
Merk op dat beide datums onjuist zijn (het is vandaag 11/10/2013), maar dat de fouten niet worden gemeld. Deze fouten worden gedetecteerd door de methode [Validate] van het model:
// validatie
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> résultats = new List<ValidationResult>();
// Datum 1
if (Date1.Date <= DateTime.Now.Date)
{
résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Date1" }));
}
// E-mail1
try
{
new MailAddress(Email1);
}
catch
{
résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Email1" }));
}
// Regexp1
try
{
DateTime.ParseExact(Regexp1, "dd/MM/yyyy", CultureInfo.CreateSpecificCulture("fr-FR"));
}
catch
{
résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Regexp1" }));
}
// de lijst met fouten weergeven
return résultats;
}
De methode [Validate] wordt pas uitgevoerd wanneer alle validaties op basis van attributen zijn doorstaan. Dit blijkt uit een laatste voorbeeld:
![]() |
5.9.2. Validatie aan de clientzijde
Alle voorgaande validaties vonden plaats aan de serverzijde. Er is dus een heen-en-terugverkeer tussen de client en de server nodig om de gebruiker op zijn fouten te wijzen. Bij validatie aan de clientzijde wordt JavaScript-code gebruikt om de gebruiker zo snel mogelijk, en in ieder geval vóór de POST, op zijn fouten te wijzen. Deze kan pas plaatsvinden wanneer alle gedetecteerde fouten zijn gecorrigeerd.
We nemen het vorige model [ViewModel11] weer op, maar geven het nu weer met de volgende weergave [Action12Get.cshtml]:
![]() |
@model Exemple_03.Models.ViewModel11
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action12Get</title>
<link rel="stylesheet" href="~/Content/Site.css" />
<script type="text/javascript" src="~/Scripts/jquery-1.8.2.min.js" ></script>
<script type="text/javascript" src="~/Scripts/jquery.validate.min.js" ></script>
<script type="text/javascript" src="~/Scripts/jquery.validate.unobtrusive.min.js" ></script>
</head>
<body>
<h3>Formulaire ASP.NET MVC - Validation 1</h3>
@using (Html.BeginForm("Action11Post", "First"))
{
<table>
<thead>
<tr>
<th>Type attendu</th>
<th>Valeur saisie</th>
<th>Message d'erreur</th>
</tr>
</thead>
<tbody>
...
</tbody>
</table>
<p>
<input type="submit" value="Valider" />
</p>
}
</body>
</html>
Opmerking: regel 13, pas de versie van jQuery aan aan die van uw versie van Visual Studio (zie hieronder).
Voor validatie aan de clientzijde moet de onderstaande regel 3 aanwezig zijn in het bestand [Web.config] van de applicatie.
<appSettings>
...
<add key="ClientValidationEnabled" value="true" />
</appSettings>
- regels 1-4: de sectie [appSettings] moet een direct onderliggend element zijn van de sectie [configuration] in het bestand [Web.config];
De weergave [Action12Get] is identiek aan de vorige weergave [Action11Get], op de regels 13-15 na. Deze voegen de JavaScript-scripts toe aan de weergave die nodig zijn voor validatie aan de clientzijde. Deze scripts bevinden zich in de map [Scripts] van het project:
![]() |
Elk script heeft een normale versie ([.js]) en een geminimaliseerde versie ([min.js]). Deze laatste versie is lichter, maar onleesbaar. Deze wordt in de productieomgeving gebruikt. De leesbare versie wordt tijdens de ontwikkeling gebruikt.
De weergave [Action12Get.cshtml] wordt weergegeven door de volgende actie [Action12Get]:
// Actie12-GET
[HttpGet]
public ViewResult Action12Get()
{
return View("Action12Get", new ViewModel11());
}
Het ingevulde formulier wordt verwerkt door de volgende actie [Action12Post]:
// Actie12-POST
[HttpPost]
public ViewResult Action12Post(ViewModel11 modèle)
{
return View("Action12Get", modèle);
}
Laten we aan de hand van een voorbeeld eens bekijken wat dit verandert:
![]() |
Zodra er een teken wordt ingevoerd in [1], verschijnt de foutmelding in [2] omdat de verwachte waarde minimaal vier tekens moet bevatten. De validatie vindt dus plaats bij elk nieuw ingevoerd teken. De foutmelding verdwijnt zodra het vierde teken is ingevoerd. Laten we vervolgens het formulier valideren:
![]() |
De URL [3] laat zien dat de [POST] niet heeft plaatsgevonden. Maar door op de knop [Valider] te klikken, zijn alle validaties aan de clientzijde geactiveerd en zijn er nieuwe foutmeldingen verschenen.
Laten we bijvoorbeeld eens kijken naar de HTML die bij de eerste invoer is gegenereerd:
<tr>
<td><label for="Chaine1">Chaîminstens vier tekens</label></td>
<td><input class="text-box single-line" data-val="true" data-val-regex="Information incorrecte" data-val-regex-pattern="^.{4,}$" data-val-required="Information requise" id="Chaine1" name="Chaine1" type="text" value="" /></td>
<td><span class="field-validation-valid" data-valmsg-for="Chaine1" data-valmsg-replace="true"></span></td>
</tr>
- op regel 3 zien we:
- de foutmelding voor het geval de invoer ontbreekt: [data-val-required],
- de foutmelding voor het geval de invoer onjuist is: [data-val-regex],
- de reguliere expressie voor de ingevoerde tekenreeks [data-val-regex-pattern];
- regel 4, andere attributen [data-x] die worden gebruikt om de eventuele foutmelding weer te geven;
De attributen [data-x] van de gegenereerde tags worden verwerkt door de JavaScript-code die we in de weergave hebben ingebed. Als deze ontbreekt, worden deze attributen simpelweg genegeerd en vindt er geen validatie aan de clientzijde plaats. Dit werkt net als in het vorige voorbeeld. Vandaar de term [unobtrusive] voor deze techniek.
5.10. Beheer van navigatie- en actielinks
We gaan de volgende twee weergaven maken om het beheer van links in een weergave te illustreren:
![]() |
- in [1] en [2] hebben we twee navigatielinks;
- in [3] is er een actielink die het formulier verstuurt. Deze dient niet om te navigeren.
Pagina 1 wordt gegenereerd door de volgende weergave [Action16Get.cshtml]:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action16Get</title>
<script>
function postForm() {
// het formulier uit het document wordt opgehaald
var form = document.forms[0];
// verzending
form.submit();
}
</script>
</head>
<body>
<h3>Navigation - page 1</h3>
<h4>@ViewBag.info</h4>
@using (Html.BeginForm("Action16Post", "Second"))
{
@Html.Label("data", "Tapez un texte")
@Html.TextBox("data")
<a href="javascript:postForm()">Valider</a>
}
<p>
@Html.ActionLink("Page 2", "Action17Get", "Second")
</p>
</body>
</html>
- regel 22: informatie die wordt geïnitialiseerd door de actie die de weergave zal genereren;
- regels 23-28: een formulier;
- regel 25: een label voor het veld [data];
- regel 26: een invoerveld met de naam [data];
- regel 27: een link van het type [submit]. Wanneer hierop wordt geklikt, wordt de JavaScript-functie [postForm] uitgevoerd (href-attribuut). Deze is gedefinieerd in de regels 12-17;
- regel 14: er wordt een verwijzing opgehaald naar het eerste formulier in het document, dat op regel 23 staat;
- regel 16: dit formulier wordt verzonden. Uiteindelijk verloopt alles alsof er op een knop van het type [submit] is geklikt. Het formulier wordt verzonden naar de controller en de actie die op regel 23 zijn gespecificeerd;
- regel 30: een navigatielink. De gegenereerde code HTML is als volgt:
<a href="/Second/Action17Get">Page 2</a>
De gebruikte methode is ActionLink(Tekst, Actie, Controller).
Pagina 2 wordt gegenereerd door de volgende weergave [Action17Get.cshtml]:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action17Get</title>
</head>
<body>
<h3>Navigation - Page 2</h3>
<h4>@ViewBag.info</h4>
<p>
@Html.ActionLink("Page 1", "Action16Get", "Second")
</p>
</body>
</html>
De acties die deze weergaven genereren, zijn de volgende:
// Actie16-GET
[HttpGet]
public ViewResult Action16Get()
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
return View("Action16Get");
}
// Actie16-POST
[HttpPost]
public ViewResult Action16Post(string data)
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}, Data={2}", RouteData.Values["controller"], RouteData.Values["action"], data);
return View("Action16Get");
}
// Actie17-GET
[HttpGet]
public ViewResult Action17Get()
{
ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
return View();
}
- regel 6: de actie [Action16Get] genereert de weergave [Action16Get.cshtml], d.w.z. pagina 1 van het voorbeeld. Deze weergave is gebaseerd op [ViewBag] (regel 5);
- regel 19: de actie [Action17Get] genereert de weergave [Action17Get.cshtml], d.w.z. pagina 2 van het voorbeeld. Deze weergave is gebaseerd op [ViewBag] (regel 21);
- regel 11: de actie [Action16Post] verwerkt het veld POST uit het formulier van de weergave [Action16Get.cshtml]. Deze actie ontvangt de parameter met de naam [data]. We herinneren ons dat dit de naam is van het invoerveld in het formulier;
- regel 13: er wordt informatie in [ViewBag] geplaatst;
- regel 14: de weergave [Action16Get.cshtml] wordt weergegeven.
De lezer wordt uitgenodigd om dit voorbeeld uit te proberen.































































