5. Beheer van de gebruikersinterface
5.1. Introduction
In de client-serverrelatie op het web stuurt de client informatie naar de server in de vorm van een reeks parameters [param1=val1¶m2=val2&...]. In onze voorgaande voorbeelden hebben we deze reeks meestal handmatig samengesteld door URL's op te roepen in de vorm van [http://localhost/appli? param1=val1¶m2=val2&...]. In de praktijk is de informatie die de client naar de server verzendt afkomstig van formulieren die de gebruiker heeft ingevuld. In dit hoofdstuk gaan we in op de opbouw daarvan. We introduceren ook de tool WebMatrix waarmee we de gebruikersinterfaces kunnen ontwerpen. De installatie van deze tool wordt beschreven in de bijlagen.
5.2. De taal HTML
5.2.1. Een voorbeeld
Laten we eens kijken naar het volgende voorbeeld, gemaakt met [Web Matrix], dat het volgende toont:
- een tabel
- een afbeelding
- een link

Laten we [WebMatrix] uitvoeren en vervolgens de optie [File/New File] kiezen:

We kiezen ervoor om een pagina HTML aan te maken. De bovenstaande gegevens zullen een bestand [d:\data\devel\aspnet\chap4\exemple1\exemple1.htm] aanmaken. [WebMatrix] biedt twee mogelijkheden om dit bestand te bewerken: de modus [Design] en de modus [HTML]:

In de modus [Design] kun je gebruikmaken van het componentenpalet HTML dat door [WebMatrix] wordt aangeboden:

Om een element uit dit palet in te voegen, hoeft u er alleen maar op te dubbelklikken en het vervolgens in het venster [Design] te plaatsen. Met de modus [HTML] kunt u het document HTML samenstellen met behulp van een teksteditor. Hiervoor moet u de syntaxis van de taal HTML kennen. Op het tabblad [HTML] is een documentskelet gegenereerd:

Het venster [HTML] is erg handig voor wie de taal HTML niet kent. Hij stelt in het venster [Design] zijn document op en controleert de gegenereerde HTML-code in het venster [HTML]. Zo krijgt hij geleidelijk aan de HTML onder de knie en kan hij vrij snel uitsluitend met de teksteditor werken, zonder de hulp van de modus [Design]. We gaan nu laten zien hoe we het document HTML kunnen opbouwen dat aan het begin van deze paragraaf is getoond. We werken in het venster [Design]. Allereerst voeren we direct de eerste tekstregel in:

- we voegen de component [Horizontal Rule] toe aan het componentenpalet:

- we voegen de component [Table] toe:

- we plaatsen de cursor in de derde rij van de tabel om deze te verwijderen met de optie [HTML/Edit Table/Delete Table Row]. Vervolgens voeren we de gewenste tekst in elke cel in:

- we plaatsen de cursor in een van de cellen van de tabel en bekijken de eigenschappen ervan. Het eigenschappenvenster wordt rechtsonder in de werkomgeving weergegeven:

- De cel wordt weergegeven door de tag HTML <TD>. We zien dus de eigenschappen van de tag <TD>. We richten onze aandacht op de tabel, die een object is dat de cel omvat. We klikken op de vervolgkeuzelijst (click to see parent HTML elements) hierboven om het object <TABLE> te selecteren:

- Het object <TABLE> heeft een eigenschap [border] die de breedte van de rand rond de cellen van de tabel bepaalt. Hier kiezen we voor border=1.

- we bewerken nu de attributen van het object <TD> van cel (1,2) om align=Center en width=200 (pixels) in te stellen. De tekst wordt in de cel gecentreerd (align=center) en de cel wordt 200 pixels breed. Om de wijziging te zien, moet u soms eerst het tabblad [HTML] selecteren en vervolgens teruggaan naar het tabblad [Design]:

- nu plaatsen we de tekst die voor de afbeelding staat:

- en vervolgens de afbeelding door te dubbelklikken op de component [image] in het palet:

- We selecteren de afbeelding om de eigenschappen ervan te bewerken:

- in het attribuut [src] voeren we de bestandsnaam in waarin de afbeelding is opgeslagen, in dit geval [univ01.gif]:

- we plaatsen de tekst die voor de link staat:

- we maken van de tekst [ici] een link naar de URL [http://istia.univ-angers.fr]. Hiervoor selecteren we de tekst en kiezen we vervolgens de optie [HTML/Insert Hyperlink]:

- we krijgen het volgende resultaat:

- we zijn er bijna. Laten we eens kijken naar de gegenereerde code HTML in het tabblad [HTML]:
<html>
<head>
</head>
<body>
<p>
Le langage HTML - 1
</p>
<hr />
<table border="1">
<tbody>
<tr>
<td>
cellule(1,1)</td>
<td align="middle" width="200">
cellule(1,2)</td>
<td>
cellule(1,3)</td>
</tr>
<tr>
<td>
cellule(2,1)</td>
<td>
cellule(2,2)</td>
<td>
cellule(2,3)</td>
</tr>
</tbody>
</table>
<p>
Une image <img src="univ01.gif" />
</p>
<p>
Le site de l'istia <a href="http://istia.univ-angers.fr">ici</a>
</p>
</body>
</html>
Er moeten nog enkele details worden geregeld. Allereerst willen we ons document een titel geven. In de modus [WebMatrix] is dit niet mogelijk. In het tabblad [HTML] vervangen we de reeks <head>..</head> door de volgende reeks:
Daarnaast willen we de tekst [Le langage HTML - 1] in grotere letters weergeven. Met de reeks <Hi>tekst</Hi> kan de tekstgrootte worden ingesteld, waarbij i varieert van 1 tot 6, van groot naar klein. Hier kiezen we voor H2. De reeks
wordt:
Het venster [Design] geeft onze wijzigingen weer:

Nu hoeven we alleen nog maar te testen met behulp van de optie [View/Start] of [F5]. [WebMatrix] vraagt om enkele gegevens om de webserver [Cassini] te starten:

We kunnen de voorgestelde standaardwaarden accepteren. De server [Cassini] wordt gestart en onze pagina wordt in een browser weergegeven:

Uit nieuwsgierigheid kunnen we controleren met welke parameters [Cassini] is gestart:

We hebben de basisprincipes van het bouwen van een HTML-pagina met [WebMatrix] besproken. De lezer wordt uitgenodigd om andere HTML-pagina’s te bouwen en telkens de gegenereerde HTML-code te controleren. Gaandeweg zal hij in staat zijn om een pagina te bouwen zonder de hulp van de modus [Design]. Een HTML-document heeft de volgende algemene vorm:
Het gehele document wordt omgeven door de tags <html>...</html>. Het bestaat uit twee delen:
<head>...</head>: dit is het niet-weergegeven gedeelte van het document. Het geeft informatie aan de browser die het document gaat weergeven. Hierin staat vaak de tag <title>...</title>, die de tekst vastlegt die in de titelbalk van de browser wordt weergegeven. Er kunnen ook andere tags in staan, met name tags die de trefwoorden van het document definiëren; trefwoorden die vervolgens door zoekmachines worden gebruikt. In dit gedeelte kunnen ook scripts voorkomen, meestal geschreven in JavaScript of VBScript, die door de browser worden uitgevoerd.
<body attributen>...</body>: dit is het gedeelte dat door de browser wordt weergegeven. De tags HTML in dit gedeelte geven aan de browser aan hoe het document er visueel „uit moet zien”. Elke browser interpreteert deze tags op zijn eigen manier. Twee browsers kunnen hetzelfde webdocument dus op verschillende manieren weergeven. Dit is doorgaans een van de hoofdbrekers voor webontwerpers.
De code HTML van het vorige document was als volgt:
<html>
<head>
<title>HTML1</title>
</head>
<body>
<h2>Le langage HTML - 1
</h2>
<hr />
<table border="1">
<tbody>
<tr>
<td>
cellule(1,1)</td>
<td align="middle" width="200">
cellule(1,2)</td>
<td>
cellule(1,3)</td>
</tr>
<tr>
<td>
cellule(2,1)</td>
<td>
cellule(2,2)</td>
<td>
cellule(2,3)</td>
</tr>
</tbody>
</table>
<p>
Une image <img src="univ01.gif" />
</p>
<p>
Le site de l'istia <a href="http://istia.univ-angers.fr">ici</a>
</p>
</body>
</html>
Element | tags en voorbeelden HTML |
<title>HTML1</title> HTML1 verschijnt in de titelbalk van de browser die het document weergeeft | |
<hr>: geeft een horizontale streep weer | |
<table-attributen>....</table>: om de tabel te definiëren <tr attributen>...</tr>: om een rij te definiëren <td attributen>...</td>: om een cel te definiëren voorbeelden: <table border="1">...</table>: het attribuut border bepaalt de dikte van de rand van de tabel <td align="center" width="200">cel(1,2)</td>: definieert een cel waarvan de inhoud cellule(1,2) zal zijn. Deze inhoud wordt horizontaal gecentreerd (align="center"). De cel heeft een breedte van 200 pixels (width="200") | |
<img src="univ01.gif" />: definieert een afbeelding waarvan het bronbestand univ01.gif op de webserver staat (src="univ01.gif"). Deze link staat in een webdocument dat is gegenereerd met de URL http://localhost/exemple1.htm. De browser zal dus de pagina http://localhost/univ01.gif opvragen om de hier genoemde afbeelding op te halen. | |
<a href="http://istia.univ-angers.fr">hier</a>: zorgt ervoor dat de tekst ici als link naar de URL URL http://istia.univ-angers.fr fungeert. |
Uit dit eenvoudige voorbeeld blijkt dat de browser, om het volledige document op te bouwen, twee verzoeken naar de server moet sturen:
http://localhost/exemple1.htm om de broncode HTML van het document op te halen
http://localhost/univ01.gif om de afbeelding univ01.gif op te halen
5.2.2. Een formulier opbouwen
Een formulier HTML is bedoeld om de gebruiker een pagina te tonen waarop hij gegevens kan invoeren, vergelijkbaar met de invoerformulieren die men in Windows tegenkomt. Het invoerformulier wordt in de vorm van een document HTML naar de browser verzonden. De browser toont het formulier aan de gebruiker, die het invult en valideert met een knop die deze functie heeft. De browser stuurt vervolgens de ingevoerde waarden naar de server voor verwerking. We zullen zien dat niet het volledige formulier naar de server wordt teruggestuurd, maar alleen de ingevoerde waarden. Het volgende voorbeeld toont een webformulier dat eveneens met WebMatrix is gemaakt:

De door [WebMatrix] gegenereerde code HTML is als volgt:
<html>
<head>
<title>Formulaire</title>
<script language="javascript">
function effacer(){
alert("Vous avez cliqué sur le bouton [Effacer]");
}
</script>
</head>
<body>
<p>
Gestion d'un formulaire
</p>
<hr />
<form name="formulaire" method="post">
<table border="1">
<tr>
<td>
Etes-vous marié(e)</td>
<td>
<p align="center">
<input type="radio" value="oui" name="rdMarie" />Oui
<input type="radio" checked value="non" name="rdMarie" />Non
</p>
</td>
</tr>
<tr>
<td>
Cases à cocher
</td>
<td>
<p align="center">
<input type="checkbox" value="un" name="C1" />1
<input type="checkbox" checked value="deux" name="C2" />2
<input type="checkbox" value="trois" name="C3" />3
</p>
</td>
</tr>
<tr>
<td>
Champ de saisie</td>
<td>
<p align="center">
<input type="text" maxlength="30" value="qqs mots" name="txtSaisie" />
</p>
</td>
</tr>
<tr>
<td>
Mot de passe</td>
<td>
<p align="center">
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
</p>
</td>
</tr>
<tr>
<td>
Boîte de saisie</td>
<td>
<p align="center">
</p>
<textarea name="areaSaisie">ligne1
ligne2</textarea>
</td>
</tr>
<tr>
<td>
ComboBox</td>
<td>
<p align="center">
</p>
<select name="cmbValeurs">
<option value="1">choix1</option>
<option value="2" selected>choix2</option>
<option value="3">choix3</option>
</select>
</td>
</tr>
<tr>
<td>
Liste à choix simple</td>
<td>
<p align="center">
</p>
<select size="3" name="lstSimple">
<option value="1" selected>liste1</option>
<option value="2">liste2</option>
<option value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</td>
</tr>
<tr>
<td>
Liste à choix multiple</td>
<td>
<p align="center">
</p>
<select multiple size="3" name="lstMultiple">
<option value="1" selected>multiple1</option>
<option value="2">multiple2</option>
<option value="3" selected>multiple3</option>
<option value="4">multiple4</option>
<option value="5">multiple5</option>
</select>
</td>
</tr>
<tr>
<td>
Bouton simple</td>
<td>
<p align="center">
<input onclick="effacer()" type="button" value="Effacer" name="btnEffacer" />
</p>
</td>
</tr>
<tr>
<td>
Bouton submit</td>
<td>
<p align="center">
<input type="submit" value="Envoyer" name="btnEnvoyer" />
</p>
</td>
</tr>
<tr>
<td>
Bouton reset</td>
<td>
<p align="center">
<input type="reset" value="Rétablir" name="btnRetablir" runat="server" />
</p>
</td>
</tr>
</table>
<input type="hidden" name="secret" value="uneValeur" />
</form>
</body>
</html>
De koppeling tussen visuele controle <--> tag HTML is als volgt:
Controle | tag HTML |
<form name="formulier" method="post"> | |
<input type="text" maxlength="30" value="een paar woorden" name="txtSaisie" /> | |
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" /> | |
<textarea name="areaSaisie">regel1 regel2</textarea> | |
<input type="radio" value="ja" name="rdMarie" />Ja <input type="radio" checked value="nee" name="rdMarie" />Nee | |
<input type="checkbox" value="één" name="C1" />1 <input type="checkbox" checked value="twee" name="C2" />2 <input type="checkbox" value="drie" name="C3" />3 | |
<select name="cmbValeurs"> <option value="1">keuze1</option> <option value="2" selected>keuze 2</option> <option value="3">keuze3</option> </select> | |
<select size="3" name="lstSimple"> <option value="1" selected>lijst1</option> <option value="2">lijst2</option> <option value="3">lijst3</option> <option value="4">lijst4</option> <option value="5">lijst5</option> </select> | |
<select multiple size="3" name="lstMultiple"> <option value="1" selected>multiple1</option> <option value="2">multiple2</option> <option value="3" selected>multiple3</option> <option value="4">multiple4</option> <option value="5">multiple5</option> </select> | |
<input type="hidden" name="secret" value="uneValeur" /> | |
<input type="submit" value="Verzenden" name="btnEnvoyer" /> | |
<input type="reset" value="Resetten" name="btnRetablir" runat="server" /> | |
<input onclick="effacer()" type="button" value="Wissen" name="btnEffacer" /> |
Laten we deze verschillende besturingselementen eens bekijken.
5.2.2.1. Het formulier
<form name="formulier" method="post"> |
<form name="..." method="..." action="...">...</form> | |
name="frmexemple": naam van het formulier 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. Deze naam is nuttig als het webdocument scripts bevat die naar elementen van het formulier moeten verwijzen. 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 de 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. Hoe zorgt een webclient ervoor dat informatie (die in het formulier staat) naar een webserver wordt verzonden? Dat hebben we in detail besproken. Er kunnen twee verschillende methoden worden gebruikt, namelijk POST en GET. Het attribuut method="méthode", met als methode 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. |
5.2.2.2. Invoerveld

<input type="text" maxlength="30" value="een paar woorden" name="txtSaisie" /> <input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" /> |
<input type="..." name="..." size=".." value=".."> De input-tag bestaat voor verschillende besturingselementen. Het is het attribuut type waarmee deze verschillende besturingselementen van elkaar kunnen worden onderscheiden. | |
type="text": geeft aan dat het een invoerveld is type="password": de tekens in het invoerveld worden vervangen door *-tekens. Dit is het enige verschil met het normale invoerveld. Dit type besturingselement is geschikt voor het invoeren van wachtwoorden. size="12": aantal zichtbare tekens in het veld – dit belet niet dat er meer tekens worden ingevoerd maxlength="30": stelt het maximale aantal tekens vast op 30 – de browser zorgt ervoor dat aan dit attribuut wordt voldaan name="txtSaisie": naam van het invoerveld value="enkele woorden": tekst die in het invoerveld wordt weergegeven. |
5.2.2.3. Invoerveld met meerdere regels

<textarea name="areaSaisie">regel1 regel2</textarea> |
<textarea ...>tekst</textarea> toont een invoerveld voor meerdere regels met aanvankelijk tekst erin | |
rows="2": aantal regels cols="'20": aantal kolommen name="areaSaisie": naam van het besturingselement |
5.2.2.4. Keuzerondjes
![]()
<input type="radio" value="ja" name="rdMarie" />Ja <input type="radio" checked value="nee" name="rdMarie" />Nee |
<input type="radio" attribuut2="waarde2" ..../>tekst toont een keuzerondje met tekst ernaast. | |
name="rdMarie": naam van het besturingselement. Keuzerondjes met dezelfde naam vormen een groep die elkaar uitsluiten: er kan slechts één worden aangevinkt. value="waarde": de waarde die aan de keuzeknop wordt toegewezen. Deze waarde mag niet worden verward met de tekst die naast de keuzeknop wordt weergegeven. Die tekst is uitsluitend bedoeld voor weergave. checked: als dit trefwoord aanwezig is, is het keuzerondje aangevinkt, anders niet. |
5.2.2.5. Selectievakjes
<input type="checkbox" value="één" name="C1" />1 <input type="checkbox" checked value="twee" name="C2" />2 <input type="checkbox" value="drie" name="C3" />3 |
![]()
<input type="checkbox" attribuut2="waarde2" ..../>tekst toont een selectievakje met tekst ernaast. | |
name="C1": naam van het besturingselement. Selectievakjes kunnen al dan niet dezelfde naam hebben. Selectievakjes met dezelfde naam vormen een groep van aan elkaar gekoppelde selectievakjes. value="waarde": waarde die aan het selectievakje wordt toegewezen. Deze waarde mag niet worden verward met de tekst die naast het selectievakje wordt weergegeven. Deze tekst is uitsluitend bedoeld voor weergave. checked: als dit trefwoord aanwezig is, is het keuzerondje aangevinkt, anders niet. |
5.2.2.6. Keuzelijst (combo)
<select name="cmbValeurs"> <option value="1">keuze1</option> <option value="2" selected>keuze2</option> <option value="3">keuze 3</option> </select> |
![]()
<select size=".." name=".."> <option [selected="selected"] [value="valeur"]>tekst</option> ... </select> geeft in een lijst de teksten weer die tussen de tags <option>...</option> staan | |
name="cmbValeurs": naam van het besturingselement. size="1": aantal zichtbare lijstitems. size="1" maakt van de lijst het equivalent van een combobox. Dit is de standaardwaarde als het attribuut [size] ontbreekt. selected="selected": als dit trefwoord bij een lijstitem aanwezig is, wordt dit item in de lijst als geselecteerd weergegeven. In ons voorbeeld hierboven wordt het lijstitem choix2 weergegeven als het geselecteerde item in de keuzelijst wanneer deze voor het eerst wordt weergegeven. value="waarde": stelt de waarde in die naar de server moet worden verzonden als het item wordt geselecteerd. Als dit attribuut ontbreekt, wordt de tekst die aan het keuzemenu is gekoppeld naar de server verzonden. |
5.2.2.7. Lijst met één selectie
<select size="3" name="lstSimple"> <option value="1" selected>lijst1</option> <option value="2">lijst2</option> <option value="3">lijst3</option> <option value="4">lijst4</option> <option value="5">lijst5</option> </select> |

<select size=".." name=".."> <option [selected] [value="valeur"]>...</option> ... </select> geeft in een lijst de teksten weer die tussen de tags <option>...</option> staan | |
dezelfde als voor de vervolgkeuzelijst die slechts één item weergeeft. Dit besturingselement verschilt alleen van de vorige vervolgkeuzelijst door het attribuut size>1. |
5.2.2.8. Lijst met meerdere selecties
<select multiple size="3" name="lstMultiple"> <option value="1" selected>multiple1</option> <option value="2">multiple2</option> <option value="3" selected>multiple3</option> <option value="4">multiple4</option> <option value="5">multiple5</option> </select> |

<select size=".." name=".." multiple> <option [selected] ] [value="valeur"]>...</option> ... </select> geeft in een lijst de teksten weer die tussen de tags <option>...</option> | |
multiple: maakt het mogelijk meerdere elementen in de lijst te selecteren. In het bovenstaande voorbeeld zijn de elementen liste1 en liste3 beide geselecteerd. |
5.2.2.9. Knop van het type button
<input onclick="effacer()" type="button" value="Wissen" name="btnEffacer" /> |
![]()
<input type="button" value="..." name="..." onclick="effacer()" ....> | |
type="button": definieert een knop. Er zijn nog twee andere soorten knoppen: de typen submit en reset. value="Wissen": de tekst die op de knop wordt weergegeven onclick="functie()": hiermee kunt u een functie definiëren die moet worden uitgevoerd wanneer de gebruiker op de knop klikt. Deze functie maakt deel uit van de scripts die in het weergegeven webdocument zijn gedefinieerd. De bovenstaande syntaxis is een javascript-syntaxis. Als de scripts in VBScript zijn geschreven, moet u onclick="functie" schrijven zonder de haakjes. De syntaxis blijft hetzelfde als er parameters aan de functie moeten worden doorgegeven: onclick="functie(val1, val2,...)" In ons voorbeeld roept een klik op de knop Effacer de volgende JavaScript-functie effacer aan: De functie effacer geeft een melding weer: ![]() |
5.2.2.10. Submit-knop
<input type="submit" value="Verzenden" name="btnEnvoyer" /> |
![]()
<input type="submit" value="Verzenden" name="btnEnvoyer"> | |
type="submit": definieert de knop als een knop om de gegevens van het formulier naar de webserver te verzenden. Wanneer de gebruiker op deze knop klikt, verzendt de browser de gegevens van het formulier naar de URL die is gedefinieerd in het action-attribuut van de <form>-tag, volgens de methode die is gedefinieerd door het method-attribuut van diezelfde tag. value="Verzenden": de tekst die op de knop wordt weergegeven |
5.2.2.11. Resetknop
<input type="reset" value="Resetten" name="btnRetablir" runat="server" /> |
![]()
<input type="reset" value="Terugzetten" name=" btnRetablir "> | |
type="reset": definieert de knop als een knop om het formulier te resetten. Wanneer de gebruiker op deze knop klikt, zet de browser het formulier terug in de staat waarin het werd ontvangen. value="Resetten" : de tekst die op de knop wordt weergegeven |
5.2.2.12. Verborgen veld
<input type="hidden" name="secret" value="uneValeur" /> |
<input type="hidden" name="..." value="..."> | |
type="hidden": geeft aan dat het een verborgen veld is. Een verborgen veld maakt deel uit van het formulier, maar wordt niet aan de gebruiker getoond. Als de gebruiker echter aan zijn browser zou vragen om de broncode weer te geven, zou hij de tag <input type="hidden" value="..."> zien en dus ook de waarde van het verborgen veld. value="eenWaarde": waarde van het verborgen veld. Wat is het nut van het verborgen veld? Hiermee kan de webserver informatie bijhouden tijdens de verzoeken van een klant. Laten we eens kijken naar een online winkelapplicatie. De klant koopt een eerste artikel art1 in een hoeveelheid q1 op een eerste pagina van een catalogus en gaat vervolgens naar een nieuwe pagina van de catalogus. Om te onthouden dat de klant q1 artikelen art1 heeft gekocht, kan de server deze twee gegevens in een verborgen veld van het webformulier op de nieuwe pagina plaatsen. Op deze nieuwe pagina koopt de klant de artikelen q2 en art2. Wanneer de gegevens van dit tweede formulier naar de server worden verzonden (submit), ontvangt de server niet alleen de informatie (q2,art2), maar ook (q1,art1), die eveneens deel uitmaakt van het formulier als een verborgen veld dat niet door de gebruiker kan worden gewijzigd. De webserver zal vervolgens de gegevens (q1,art1) en (q2,art2) in een nieuw verborgen veld plaatsen en een nieuwe cataloguspagina verzenden. En zo verder. |
5.3. Verzending van formulierwaarden naar een webserver door een browser
Uit het vorige hoofdstuk weten we al hoe een client informatie naar de server verstuurt. Dit gebeurt via:
- een verzoek met de URL HTTP GET?param1=va1¶m2=val2&....
- een verzoek HTT POST url gevolgd door een document met de parameterreeks param1=va1¶m2=val2&....
De browser zal een van deze twee methoden gebruiken, afhankelijk van of het attribuut [method] van de tag [form] de waarde GET of POST heeft. Dat gaan we nu laten zien. De pagina die we eerder hebben bekeken, is een statische pagina. Om toegang te krijgen tot de HTTP-headers die worden verzonden door de browser die dit document opvraagt, zetten we deze om in een dynamische pagina voor een .NET-webserver (IIS of Cassini). De eerdere statische code wordt in een bestand [formulaire_get.aspx] geplaatst en de inhoud ervan is als volgt:
<%@ Page src="formulaire_get.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="formulaire_get" %>
<html>
<head>
<title>Formulaire</title>
<script language="javascript">
function effacer(){
alert("Vous avez cliqué sur le bouton [Effacer]");
}
</script>
</head>
<body>
.....
</body>
</html>
De bovenstaande presentatiepagina hoort bij de controller [formulaire_get.aspx.vb]:
Public Class formulaire_get
Inherits System.Web.UI.Page
Private Sub Page_Init(ByVal Sender As Object, ByVal e As System.EventArgs) Handles MyBase.Init
' de huidige aanvraag wordt opgeslagen in request.txt in de paginamap
Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
Me.Request.SaveAs(requestFileName, True)
End Sub
End Class
Bij elke oproep van het document [formulaire_get.aspx] wordt de aanvraag van de klant door de procedure Page_Init opgeslagen in een bestand [request.txt]. We zijn deze werkwijze al eerder tegengekomen, dus zullen we niet verder ingaan op de controller.
5.3.1. Methode GET
Laten we een eerste test uitvoeren, waarbij in de code HTML van het document de tag FORM als volgt is gedefinieerd:
<form name="formulaire" method="get">
We plaatsen de bestanden [formulaire_get.aspx] en [formulaire_get.aspx.vb] in een map <application-path> en starten de Cassini-server met de parameters (<application-path>,/form2). We roepen de URL http://localhost/form2/formulaire_get.aspx op:

De browser heeft zojuist een verzoek verzonden en we weten dat dit is opgeslagen in het bestand [request.txt]. Laten we de inhoud ervan eens bekijken:
GET /form2/formulaire_get.aspx HTTP/1.1
Cache-Control: max-age=0
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316
De browser heeft een verzoek HTTP GET gebruikt om de URL [http://localhost/form2/formulaire_get.aspx] op te vragen. Dit is altijd het geval wanneer de URL door de gebruiker wordt opgegeven. We vullen het formulier als volgt in:

We gebruiken de bovenstaande knop [Envoyer]. De code HTML is als volgt:
Bij het klikken op een knop van het type [Submit], stuurt de browser de formulierparameters (tag <form>) naar de URL die is opgegeven in het attribuut [action] van de tag <form action="URL">, indien deze bestaat. Als dit attribuut niet bestaat, worden de formulierparameters verzonden naar de URL die het formulier heeft geleverd. Dat is hier het geval. De knop [Envoyer] zou dus moeten leiden tot een verzoek van de browser aan de URL [http://localhost/form2/formulaire_get.aspx], waarbij de formulierparameters worden doorgegeven. Aangezien de pagina [formulaire_get.aspx] het ontvangen verzoek onthoudt, zouden we moeten weten hoe de client deze parameters heeft doorgegeven. Laten we het eens proberen. We klikken op de knop [Envoyer]. We ontvangen het volgende antwoord van de browser:

Dit is de oorspronkelijke pagina, maar we zien dat de waarde URL in het veld [Adresse] van de browser is gewijzigd. Deze is nu als volgt:
http://localhost/form2/formulaire_get.aspx?rdMarie=ja&C1=één&C2=twee&txtSaisie=programmering+asp.net&txtMdp=unMotDePasse&areaSaisie=de+basisprincipes+van+de%0D%0Awebprogrammering%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Verzenden&secret=uneValeur
We zien dat de keuzes die in het formulier zijn gemaakt, terug te vinden zijn in de URL. Laten we eens kijken naar de inhoud van het bestand [request.txt], waarin het verzoek van de klant is opgeslagen:
GET /form2/formulaire_get.aspx?rdMarie=oui&C1=un&C2=deux&txtSaisie=programmation+asp.net&txtMdp=ceciestsecre&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Envoyer&secret=uneValeur HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/form2/formulaire_get.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316
We zien een verzoek HTTP dat sterk lijkt op het verzoek dat de browser aanvankelijk had gedaan toen hij het document opvroeg zonder parameters door te geven. Er zijn twee verschillen:
De formulierparameters zijn achter de URL van het document toegevoegd in de vorm ?param1=val1¶m2=val2&... | |
De klant geeft met deze header HTTP de URL aan van het document dat hij aan het bekijken was toen hij de aanvraag indiende |
Laten we eens nader bekijken hoe de parameters zijn doorgegeven in de opdracht GET URL?param1=waarde1¶m2=waarde2&... HTTP/1.1, waarbij de parami de namen zijn van de besturingselementen van het webformulier en de valeuri de waarden die eraan zijn gekoppeld. Hieronder presenteren we een tabel met drie kolommen:
- kolom 1: bevat de definitie van een besturingselement HTML uit het voorbeeld
- kolom 2: toont hoe dit besturingselement in een browser wordt weergegeven
- kolom 3: toont de waarde die door de browser naar de server wordt verzonden voor het besturingselement uit kolom 1, in de vorm zoals deze voorkomt in de verzoek-URL GET uit het voorbeeld
besturingselement HTML | weergave vóór validatie | teruggestuurde waarde(n) |
<input type="radio" value="ja" name="rdMarie" />Ja <input type="radio" checked value="nee" name="rdMarie" />Nee | rdMarie=ja - de waarde van het attribuut value van de knop die door de gebruiker is aangevinkt. | |
<input type="checkbox" value="een" name="C1" />1 <input type="checkbox" checked value="twee" name="C2" />2 <input type="checkbox" value="drie" name="C3" />3 | C1=één C2=twee - waarden van de attributen value van de selectievakjes die door de gebruiker zijn aangevinkt | |
<input type="text" maxlength="30" value="qqs woorden" name="txtSaisie" /> | txtInvoer=programmering+asp.net - tekst die door de gebruiker in het . Spaties zijn vervangen door het teken + | |
<input type="password" maxlength="12" size="12" value="eenWachtwoord" name="txtMdp" /> | txtMdp=ditisgeheim - tekst die door de gebruiker in het . De daadwerkelijk ingevoerde tekst was "ditisgeheim". Het laatste teken is verloren gegaan omdat het attribuut maxlength="12" het aantal tekens tot 12. | |
<textarea name="areaSaisie"> regel1 regel2</textarea> | ![]() | invoergebied=de+basisprincipes+van+ de%0D%0A webprogrammering+ - tekst die door de gebruiker in het . %OD%OA is het teken voor regeleinde. De spaties zijn vervangen door het teken + |
<select name="cmbValeurs"> <option value="1">keuze1 </option> <option value="2" selected>keuze2 </option> <option value="3">keuze 3 </option> </select> | cmbWaarden=3 - door de gebruiker gekozen waarde in de lijst met één selectie | |
<select size="3" name="lstSimple"> <option value="1" selected>lijst1</option> <option value="2">lijst2 </option> <option value="3">lijst3 </option> <option value="4">lijst4 </option> <option value="5">lijst5 </option> </select> | ![]() | lstSimple=3 - door de gebruiker gekozen waarde in de lijst met één selectie |
<select multiple size="3" name="lstMultiple"> <option value="1" selected>multiple1 </option> <option value="2">multiple2 </option> <option value="3" selected>multiple3 </option> <option value="4">multiple4 </option> <option value="5">multiple5 </option> </select> | ![]() | lstMultiple=2 lstMultiple=4 - door de gebruiker geselecteerde waarden in de lijst met meerdere selectiemogelijkheden |
<input type="submit" value="Verzenden" name="btnVerzenden" /> | btnEnvoyer=Verzenden - naam en attribuut value van de knop die is gebruikt om de gegevens van het formulier naar de server | |
<input type="hidden" name="secret" value="eenWaarde" /> | secret=eenWaarde - attribuut value van het verborgen veld |
Je kunt je afvragen wat de server heeft gedaan met de parameters die we hem hebben doorgegeven. Eigenlijk niets. Bij ontvangst van het commando
GET /form2/formulaire_get.aspx?rdMarie=oui&C1=un&C2=deux&txtSaisie=programmation+asp.net&txtMdp=ceciestsecre&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Envoyer&secret=uneValeur HTTP/1.1
De webserver heeft de parameters doorgegeven aan URL naar het document [http://localhost/form2/formulaire_get.aspx], c.a.d, naar het document dat we aanvankelijk hadden opgesteld. We hebben geen code geschreven om de parameters die de client ons stuurt op te halen en te verwerken. Het is dus alsof het verzoek van de client simpelweg luidt:
Om deze reden hebben we, als reactie op onze knop [Envoyer], dezelfde pagina ontvangen als die we aanvankelijk kregen bij het opvragen van de URL en [http://localhost/form2/formulaire_get.aspx] zonder parameters.
5.3.2. Methode POST
Het document HTML is nu zo geconfigureerd dat de browser de methode POST gebruikt om de formulierwaarden naar de webserver te verzenden. Hiervoor kopiëren we het bestand [formulaire_get.aspx] naar [formulaire_post.aspx] en wijzigen we alleen de tag <form> in [formulaire_post.aspx]:
<%@ Page src="formulaire_get.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="formulaire_get" %>
<html>
<head>
...
</head>
<body>
<p>
Gestion d'un formulaire
</p>
<hr />
<form name="formulaire" method="post">
<table border="1">
Het is niet nodig om de controller [formulaire_get.aspx.vb] te vervangen, dus laten we deze in de huidige staat. We vragen het nieuwe document aan via de URL [http://localhost/form2/formulaire_post.aspx], vullen het formulier in zoals bij de methode GET en verzenden de parameters naar de server met de knop [Envoyer]. We ontvangen de volgende responspagina van de server:

We krijgen dus hetzelfde resultaat als bij de methoden GET en c.a.d: de startpagina. Er is één verschil op te merken: in het veld [Adresse] van de browser verschijnen de doorgegeven parameters niet. Laten we nu eens kijken naar het verzoek dat door de client is verzonden en dat is opgeslagen in het bestand [request.txt]:
POST /form2/formulaire_post.aspx HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Content-Length: 222
Content-Type: application/x-www-form-urlencoded
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0,1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/form2/formulaire_post.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316
rdMarie=oui&C1=un&C2=deux&txtSaisie=programmation+asp.net&txtMdp=ceciestsecre&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lstSimple=3&lstMultiple=2&lstMultiple=4&btnEnvoyer=Envoyer&secret=uneValeur
Er verschijnen nieuwe gegevens in de query HTTP van de klant:
de query GET is vervangen door een query POST. De parameters staan niet meer in de eerste regel van de query. We zien dat ze nu na een lege regel achter de query HTTP staan. Hun codering is identiek aan die in de query GET. | |
aantal „verzonden” tekens, c.a.d. Het aantal tekens dat de webserver moet lezen na ontvangst van de headers HTTP om het document op te halen dat de client naar hem verstuurt. Het document in kwestie is hier de lijst met waarden van het formulier. | |
geeft het type document aan dat de client na de headers HTTP zal verzenden. Het type [application/x-www-form-urlencoded] geeft aan dat het een document is dat formulierwaarden bevat. |
Er zijn twee methoden om gegevens naar een webserver te verzenden: GET en POST. Is de ene methode beter dan de andere? We hebben gezien dat als de waarden van een formulier door de browser werden verzonden met de methode GET, de browser in het veld Adresse de gevraagde URL weergeeft in de vorm URL?param1=val1¶m2=val2&.... Dit kan als een voordeel of als een nadeel worden gezien:
- een voordeel als men de gebruiker de mogelijkheid wil bieden om deze geconfigureerde URL in zijn favoriete links op te nemen
- een nadeel als men niet wil dat de gebruiker toegang heeft tot bepaalde informatie in het formulier, zoals bijvoorbeeld verborgen velden
Vanaf nu zullen we in onze formulieren vrijwel uitsluitend de methode POST gebruiken.
5.4. Server-side verwerking van formulierwaarden
5.4.1. Overzicht van het voorbeeld
Nu we het verband hebben gelegd tussen de tag HTML <form method="GET/POST" ...> en de manier waarop de browser de formulierwaarden verstuurt, weten we hoe we deze aan de serverzijde kunnen ophalen. Het antwoord vonden we in het vorige hoofdstuk:
- als de methode van de tag <form> GET is, worden de waarden van de parameters opgehaald uit de verzameling [Request.QueryString]
- als de methode van de tag <form> POST is, worden de waarden van de „gepostte” parameters opgehaald uit de verzameling [Request.Form]. Hier moet een verduidelijking worden gegeven. De tag <form> kan met behulp van het attribuut [action] de doel-URL van de GET of de POST specificeren. Deze URL kan heel goed worden geconfigureerd, of er nu sprake is van een GET of een POST, in de vorm action="url?param1=val1¶m2=val2&..". Deze parameters worden vervolgens toegevoegd aan de parameters die tussen de tags <form> en </form> staan en die via een GET of een POST naar de server worden verzonden. Omdat ze deel uitmaken van de doel-URL, worden ze opgehaald in de verzameling [Request.QueryString], ongeacht of het om een GET of een POST gaat.
We schrijven nu een applicatie MVC met twee weergaven:
- de eerste weergave is het voorgaande formulier. We noemen deze [vue_formulaire].
- De tweede weergave is een informatiepagina met een overzicht van de waarden die op de eerste pagina zijn ingevoerd. Via een link kan men terugkeren naar het formulier. We noemen deze weergave [vue_confirmation].
De weergave [vue_formulaire] wordt naar de gebruiker gestuurd, die deze invult en valideert. Vlak voor de validatie zou deze er als volgt uit kunnen zien:

De gebruiker gebruikt de knop [Envoyer] om zijn invoer te valideren. Hij ontvangt vervolgens de volgende weergave [vue_validation]:

5.4.2. De controller van de applicatie
In het vorige hoofdstuk hebben we gezien dat we de rol van controller voor een applicatie MVC kunnen toewijzen aan het bestand [global.asax], waar alle verzoeken van de clients doorheen lopen. We hebben al een op deze manier opgebouwde applicatie MVC gepresenteerd en volgen hier het toen gepresenteerde ontwikkelingsmodel. Het bestand [global.asax] ziet er als volgt uit:
Het bestaat uit één enkele regel die verwijst naar de controller in het bestand [global.asax.vb]:
Imports System
Imports System.Web
Imports System.Web.SessionState
Public Class Global
Inherits System.Web.HttpApplication
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
' de uit te voeren actie wordt opgehaald
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' de actie wordt uitgevoerd
Select Case action
Case "init"
Server.Transfer("formulaire.aspx", False)
Case "validation"
Server.Transfer("validation.aspx", True)
Case Else
Server.Transfer("formulaire.aspx", True)
End Select
End Sub
End Class
Het principe van de controller is als volgt:
- de controller verwacht in de doel-URL een reeks parameters die de parameter [action] bevat. Als deze ontbreekt, wordt er gehandeld alsof [action=init] in de reeks parameters stond.
- Er worden slechts twee acties herkend:
- init: het vooraf ingevulde formulier wordt aan de klant geleverd
- validation: de klant krijgt de pagina te zien waarop zijn invoer wordt bevestigd
- Als de actie niet een van de voorgaande is, wordt er gehandeld alsof [action=init] was opgegeven. Er zou ook een foutpagina kunnen worden weergegeven.
5.4.3. Verwerking van de actie init
Wanneer de controller de actie „init“ verwerkt, moet hij een vooraf ingevuld formulier genereren. Het is de taak van de pagina [formulaire.aspx] om dit te doen. De code ervan is als volgt:
<HTML>
<HEAD>
<title>Formulaire</title>
<script language="javascript">
function effacer(){
alert("Vous avez cliqué sur le bouton [Effacer]");
}
function raz(liste){
liste.selectedIndex=-1
}
</script>
</HEAD>
<body>
<p>
Gestion d'un formulaire
</p>
<hr>
<form name="formulaire" method="post" action="?action=validation">
<table border="1">
<tr>
<td>
Etes-vous marié(e)</td>
<td>
<p align="center">
<input type="radio" value="oui" name="rdMarie">Oui <input type="radio" checked value="non" name="rdMarie">Non
</p>
</td>
</tr>
....
<td>
<select size="3" name="lstSimple">
<option value="1" selected>liste1</option>
<option value="2">liste2</option>
<option value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
<INPUT type="button" value="Raz" name="btnRazSimple" onclick="raz(lstSimple)">
</td>
....
<td>
<select multiple size="3" name="lstMultiple">
<option value="1" selected>multiple1</option>
<option value="2">multiple2</option>
<option value="3" selected>multiple3</option>
<option value="4">multiple4</option>
<option value="5">multiple5</option>
</select>
<INPUT type="button" value="Raz" name="btnRazMultiple" onclick="raz(lstMultiple)">
</td>
...
</table>
<input type="hidden" name="secret" value="uneValeur">
</form>
</body>
</HTML>
We zien hier de code HTML uit het eerder besproken formulier terug, op enkele verschillen na. De code van de tag <form> is gewijzigd:
<form name="formulaire" method="post" action="?action=validation">
- post: de waarden die door de gebruiker zijn ingevoerd en vervolgens naar de server worden verzonden wanneer de knop van het type [submit] wordt gebruikt, zullen worden verzonden via de methode HTTP POST
- actie: de syntaxis action="url" wordt gebruikt om de URL aan te geven waarnaar de formulierwaarden moeten worden verzonden. Deze URL kan een reeks parameters bevatten in de vorm param1=val1¶m2=val2&... Dat is hier het geval: we geven de parameter [action=validation] door om de controller aan te geven welke actie hij moet ondernemen. Merk op dat deze reeks parameters niet wordt voorafgegaan door een webadres. De browser zal de formulierparameters dan verzenden naar het adres dat dit formulier heeft aangeleverd. In ons hierboven gepresenteerde voorbeeld is dit adres [http://localhost/mvcform1]. De browser zal dus een verzoek [POST /mvcform1?action=validation] sturen naar de machine [localhost].
Er zijn knoppen toegevoegd waarmee de gebruiker de selectie van de elementen in de lijsten [lstSimple] en [lstMultiple] kan opheffen:

Dit resulteert in de volgende code HTML:
<td>
<select size="3" name="lstSimple">
<option value="1" selected>liste1</option>
<option value="2">liste2</option>
<option value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
<INPUT type="button" value="Raz" name="btnRazSimple" onclick="raz(lstSimple)">
</td>
....
<td>
<select multiple size="3" name="lstMultiple">
<option value="1" selected>multiple1</option>
<option value="2">multiple2</option>
<option value="3" selected>multiple3</option>
<option value="4">multiple4</option>
<option value="5">multiple5</option>
</select>
<INPUT type="button" value="Raz" name="btnRazMultiple" onclick="raz(lstMultiple)">
</td>
Als je op een knop [Raz] klikt, wordt elk element uit de lijst waarmee deze is gekoppeld, gedeselecteerd. Laten we de lijst [lstMultiple] als voorbeeld nemen. Een klik op de bijbehorende knop [Raz] zorgt ervoor dat de JavaScript-functie [raz(lstMultiple)] wordt uitgevoerd. Ter herinnering: de JavaScript-code van een HTML-document dat door een browser wordt weergegeven, wordt door diezelfde browser uitgevoerd en niet door de server. JavaScript is een zeer veelzijdige taal waarmee pagina’s een dynamisch karakter kunnen krijgen zonder tussenkomst van de server. De functie [raz] is als volgt:
Deze functie ontvangt een parameter die een JavaScript-object is dat een lijst HTML vertegenwoordigt. Dit object heeft eigenschappen en methoden. Een van deze eigenschappen is [selectedIndex], waarvan de waarde het nummer is van de eerste geselecteerde optie in de lijst HTML. Als er geen is geselecteerd, is de waarde van deze eigenschap -1. Omgekeerd komt het toekennen van een waarde aan deze eigenschap neer op het selecteren van een nieuw element in de lijst HTML, en het toekennen van de waarde -1 komt neer op het niet selecteren van enig element. Dat is wat hier gebeurt.
Tot slot valt op dat de presentatiecode [formulaire.aspx] niet vergezeld gaat van een controller [formulaire.aspx.vb]. Er is namelijk geen enkel dynamisch onderdeel dat door de server wordt gegenereerd in het document HTML, dus is er geen behoefte aan een controller.
5.4.4. Verwerking van de validatieactie
Wanneer de controller de actie „validatie“ verwerkt, moet deze een pagina genereren met een overzicht van de door de gebruiker ingevoerde waarden. Het is de taak van de pagina [validation.aspx] om dit te doen. Visueel ziet de pagina er als volgt uit:

De code HTML is als volgt:
<%@ Page src="validation.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="validation" %>
<HTML>
<HEAD>
<title>validation</title>
</HEAD>
<body>
<P>Valeurs saisies</P>
<HR width="100%" SIZE="1">
<TABLE id="Table1" cellSpacing="1" cellPadding="1" width="300" border="1">
<TR>
<TD width="84">rdMarie</TD>
<TD><% =rdMarie%></TD>
</TR>
<TR>
<TD width="84">C1</TD>
<TD><%=C1%></TD>
</TR>
<TR>
<TD width="84">C2</TD>
<TD><%=C2%></TD>
</TR>
<TR>
<TD width="84">C3</TD>
<TD><%=C3%></TD>
</TR>
<TR>
<TD width="84">txtSaisie</TD>
<TD><%=txtSaisie%></TD>
</TR>
<TR>
<TD width="84">txtMdp</TD>
<TD><%=txtMdp%></TD>
</TR>
<TR>
<TD width="84">areaSaisie</TD>
<TD><%=areaSaisie%></TD>
</TR>
<TR>
<TD width="84">cmbValeurs</TD>
<TD><%=cmbValeurs%></TD>
</TR>
<TR>
<TD width="84">lstSimple</TD>
<TD><%=lstSimple%></TD>
</TR>
<TR>
<TD width="84">lstMultiple</TD>
<TD><%=lstMultiple%></TD>
</TR>
<TR>
<TD width="84">secret</TD>
<TD><%=secret%></TD>
</TR>
</TABLE>
</body>
</HTML>
De dynamische delen <%=variabele%> van het document worden berekend door de bijbehorende controller [validation.aspx.vb]:
Imports System.Text.RegularExpressions
Public Class validation
Inherits System.Web.UI.Page
Protected rdMarie As String
Protected C1 As String
Protected C2 As String
Protected C3 As String
Protected txtSaisie As String
Protected txtMdp As String
Protected areaSaisie As String
Protected cmbValeurs As String
Protected lstSimple As String
Protected lstMultiple As String
Protected secret As String
Protected delimiteur As New Regex("\r\n")
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'de verzonden parameters worden opgehaald
rdMarie = getValue("rdMarie")
C1 = getValue("C1")
C2 = getValue("C2")
C3 = getValue("C3")
txtSaisie = getValue("txtSaisie")
txtMdp = getValue("txtMdp")
areaSaisie = String.Join(",", delimiteur.Split(getValue("areaSaisie")))
cmbValeurs = getValue("cmbValeurs")
lstSimple = getValue("lstSimple")
lstMultiple = getValue("lstMultiple")
secret = getValue("secret")
End Sub
Private Function getValue(ByVal champ As String) As String
' haalt de waarde op van het veld [champ] uit de verzonden aanvraag
' iets?
If Request.Form(champ) Is Nothing Then Return ""
' de waarde(n) van het veld worden opgehaald
Dim valeurs() As String = Request.Form.GetValues(champ)
Dim valeur As String = ""
Dim i As Integer
For i = 0 To valeurs.Length - 1
valeur += "[" + valeurs(i) + "]"
Next
Return valeur
End Function
End Class
De berekening van de weer te geven waarden vindt plaats in de procedure [Form_Load]. De waarde van een "gepost" veld wordt verkregen via de functie getValue(C), waarbij C de naam van het veld is. De belangrijkste punten van deze functie zijn de volgende:
- als C niet in de geposte parameterreeks voorkomt, wordt de lege tekenreeks als waarde voor C geretourneerd
- anders wordt de array met waarden van veld C opgehaald via [Request.Form.GetValues(C)]. Deze worden samengevoegd tot een tekenreeks in de vorm [val1][val2]...[valn], waarbij [vali] de waarde nr. i van het veld C is
Het veld [areaSaisie] wordt op een bijzondere manier verwerkt. De waarde ervan wordt door de browser verzonden in de vorm areaSaisie=regel1\r\nregel2\r\n... waarbij \r het codetekens ASCII 13 (carriage return) is en \n het codetekens ASCII 10 (regelsprong). De functie getValue(areaSaisie) is dus de tekenreeks "regel1\r\nregel2\r\n...". Deze tekenreeks wordt door de methode [Regex.Split] in regels opgesplitst. We krijgen dan een array van tekenreeksen {regel1,regel2,...}. Deze array wordt door de methode [String.Join] omgezet in de tekenreeks "regel1,regel2,...". Het is deze laatste tekenreeks die wordt weergegeven als waarde van het veld [areaSaisie]. Het doel was hier om te laten zien hoe men de verschillende regels van een veld HTML van het type [TextArea] kon verkrijgen.
5.4.5. Tests
We plaatsen alle bestanden (global.asax, global.asax.vb, formulaire.aspx, validation.aspx, validation.aspx.vb) in een map <application-path>. We starten de Cassini-server met de parameters (<application-path>,/mvcform1). We maken in de map <application-path> een leeg bestand [default.aspx] aan en roepen vervolgens de URL [http://localhost/mvcform1] op. Aangezien [/mvcform1] het virtuele pad naar een map is en niet naar een document, zal de webserver het document [default.aspx] weergeven als dit aanwezig is. Daarom hebben we dit document aangemaakt. Voordat het wordt weergegeven, wordt het script [global.asax] uitgevoerd, waardoor uiteindelijk de pagina [formulaire.aspx] wordt weergegeven. Daarom mag het bestand [default.aspx] leeg zijn.
Stel dat het gevalideerde formulier er als volgt uitziet:

Als je de knop [Envoyer] gebruikt, wordt de volgende pagina weergegeven:

Laten we allereerst de URL van het antwoord bekijken: [http://localhost/mvcform1/?action=validation]. Dit is de URL van het attribuut [action] van de tag <form> van het formulier [formulaire.aspx]:
<form name="formulaire" method="post" action="?action=validation">
Laten we de waarden die voor de verschillende velden van het formulier zijn verkregen een voor een bekijken:
veld | waarde | HTML | opmerkingen |
rdMarie | ja | <input type="radio" value="ja" name="rdMarie">Ja <input type="radio" checked value="nee" name="rdMarie">Nee | de verkregen waarde is het attribuut [value] van de aangevinkte knop |
C1 | een | <input type="checkbox" value="een" name="C1">1 | idem |
C2 | twee | <input type="checkbox" checked value="twee" name="C2">2 | idem |
C3 | <input type="checkbox" value="drie" name="C3">3 | deze knop is niet door de gebruiker aangevinkt. De waarde ervan is dus niet door de browser verzonden. In de code was de voorwaarde [Request.Form("C3") is Nothing] dus waar. | |
txtSaisie | Programmeren asp.net | <input type="text" ... name="txtSaisie"> | de verkregen waarde is de tekst die op het moment van het verzenden in het invoerveld staat |
txtMdp | mdp | <input type="password" ...name="txtMdp"> | idem |
areaSaisie | de basisprincipes van webprogrammering | <textarea name="areaSaisie"> ...</textarea> | idem |
cmbValeurs | 3 | <select name="cmbValeurs"> ... <option value="3">keuze3</option> </select> | de verkregen waarde is het attribuut [value] van de geselecteerde optie |
lstSimple | 3 | <select size="3" name="lstSimple"> .... <option value="3">lijst3</option> ... </select> | idem |
lstMultiple | 2 4 | <select multiple size="3" name="lstMultiple"> ... <option value="2">multiple2 </option> ... <option value="4">multiple4 </option> ... </select> | de verkregen waarden zijn die van de attributen [value] van de geselecteerde opties |
geheim | uneValeur | <input type="hidden" name="secret" value="eenWaarde"> | de verkregen waarde is het attribuut [value] van het verborgen veld |
Laten we nu eens kijken naar de lijsten. Stel dat de status van het formulier op het moment van validatie als volgt is:

- de optie [choix1] is geselecteerd in de comboBox
- er is geen optie geselecteerd in de twee andere lijsten. We hebben de knoppen [Raz] gebruikt om dit te bereiken.
Dit is de pagina die na het valideren wordt weergegeven:

Wanneer er geen waarde in een lijst is geselecteerd, verstuurt de browser geen parameter daarvoor. In de code van [validation.aspx.vb] zijn de uitdrukkingen [Request.Form("lstSimple")] en [Request.Form("lstMultiple")] dus gelijk aan de constante [Nothing], vandaar het hierboven weergegeven resultaat.
5.5. De status van een pagina behouden
5.5.1. De status van een pagina behouden met een sessie
We kopiëren de volledige vorige applicatie naar een nieuwe map. We voegen een link toe aan de pagina [validation.aspx] waarmee de gebruiker terug kan keren naar het formulier:

De wijziging die op de pagina [validation.aspx] moet worden aangebracht, is het toevoegen van de link:
.....
<TR>
<TD width="84">secret</TD>
<TD><%=secret%></TD>
</TR>
</TABLE>
<P>
<a href="?action=formulaire">Retour au formulaire</a>
</P>
</body>
</HTML>
Het attribuut [href] van de link heeft als waarde een URL met als enige parameter [action=formulaire], waardoor de server weet dat hij het formulier moet weergeven zoals het was op het moment dat het werd gevalideerd. Er is dus een verschil met de actie [init], die een vooraf gedefinieerd formulier weergeeft. De URL met parameter [?action=formulaire] heeft in feite geen URL. Deze zal dus dezelfde zijn als die waarmee de validatiepagina werd weergegeven. Zoals we ons uit de vorige studie herinneren, is dit de URL van de applicatiemap. Het verzoek zal dus via de controller verlopen. Deze moet nu de actie [formulaire] verwerken. De code van [global.asax.vb] wordt als volgt aangepast:
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
' de uit te voeren actie wordt opgehaald
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' de actie wordt uitgevoerd
Select Case action
Case "init"
Server.Transfer("formulaire.aspx", False)
Case "validation"
Server.Transfer("validation.aspx", True)
Case "formulaire"
Server.Transfer("formulaire.aspx", True)
Case Else
Server.Transfer("formulaire.aspx", True)
End Select
End Sub
Als de actie "formulier" is, sturen we de aanvraag gewoon door naar de pagina [formulaire.aspx]. We weten dat deze pagina een vooraf gedefinieerd formulier weergeeft waarin geen variabele onderdelen voorkomen. Deze pagina kan het formulier dus niet weergeven met de waarden die het had toen het werd gevalideerd. We willen dit punt hier benadrukken. Als alle bestanden van de applicatie in <application-path> zijn geplaatst, starten we Cassini met de parameters (<application-path>,/mvcform2) en vragen we vervolgens de URL [http://localhost/mvcform2] op. We krijgen de volgende pagina te zien (gedeeltelijke weergave):

We vullen het formulier als volgt in en verzenden het vervolgens:

We krijgen de volgende bevestigingspagina te zien:

We gebruiken de link [Retour au formulaire] die op de bovenstaande pagina staat (maar niet wordt weergegeven). We krijgen het volgende antwoord van de server:

We stellen vast dat:
- de opgevraagde URL inderdaad de parameter action=formulier bevat, zoals gewenst
- het weergegeven formulier de ingevoerde waarden kwijt is.
We weten waarom we de ingevoerde waarden niet terugvinden. Als we de code van het document [formulaire.aspx] bekijken, zien we dat alles statisch is en dat het daardoor telkens dezelfde pagina moet weergeven. Het is duidelijk dat we deze code dynamisch moeten maken. De code moet de door de gebruiker gevalideerde waarden weergeven. Maar waar moeten we deze opslaan?
Laten we de ijzeren wet van het stateloze protocol HTTP nog eens in herinnering brengen:
- de URL [http://localhost/mvcform2] wordt opgevraagd – er wordt een antwoord ontvangen. Er is een verbinding TCP-IP geopend tussen de client en de server aan het begin van de aanvraag en beëindigd aan het einde van het antwoord.
- De gebruiker voert gegevens in en bevestigt deze. De URL [http://localhost/mvcform2/?action=validation] wordt opgevraagd – er wordt een antwoord ontvangen. Er is een nieuwe verbinding TCP-IP geopend en vervolgens gesloten tussen de twee partijen.
- De gebruiker gebruikt de link [Retour au formulaire]. De URL [http://localhost/mvcform2/?action=formulaire] wordt opgevraagd – er wordt een antwoord ontvangen. Er is opnieuw een verbinding TCP-IP geopend en vervolgens gesloten tussen de twee partners.
De vraag-antwoordcycli staan los van elkaar omdat elk daarvan een nieuwe verbinding TCP-IP gebruikt. Wanneer een client-servertoepassing één enkele verbinding TCP-IP gebruikt voor een reeks uitwisselingen, kan de server een client identificeren via zijn verbinding. Hij kan dus informatie opslaan die hij aan een specifieke verbinding koppelt en zo de uitwisselingen bijhouden. Wanneer de uitwisselingen via verschillende verbindingen plaatsvinden, kan de server een client niet aan een verbinding koppelen. Er is een andere manier nodig. In het vorige hoofdstuk hebben we er een geïntroduceerd: het sessiemechanisme. Hiermee kunnen de vraag-antwoordcycli informatie opslaan in een [Session]-object dat toegankelijk is voor alle opeenvolgende cycli.
Nu we een applicatie MVC met sessie hebben, kunnen we het bestand [global.asax] niet meer als controller gebruiken, zoals in het vorige hoofdstuk is getoond. De rol van applicatiecontroller moet worden vervuld door een speciale pagina die hiervoor is bestemd. In dit geval is dat de pagina [main.aspx]. We gaan als volgt te werk:
- wanneer de gebruiker zijn gegevens valideert (actie=validatie), slaat de controller [main.aspx.vb] deze op in de huidige sessie voordat de validatiepagina wordt weergegeven.
- wanneer het formulier met de ingevoerde waarden moet worden weergegeven (actie=formulier), haalt de controller [main.aspx.vb] deze uit de sessie en plaatst ze in de context voordat het formulier wordt weergegeven.
5.5.2. De nieuwe applicatiecontroller
De applicatiecontroller bestaat uit de twee bestanden [main.aspx, main.aspx.vb]:
[main.aspx]
[main.aspx.vb]
Imports System.Collections.Specialized
Imports Microsoft.VisualBasic
Public Class main
Inherits System.Web.UI.Page
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' de uit te voeren actie wordt opgehaald
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' de actie wordt uitgevoerd
Select Case action
Case "init"
' het vooraf ingevulde formulier wordt weergegeven
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
Case "validation"
' de bevestigingspagina wordt weergegeven nadat de verzonden waarden in de sessie zijn opgeslagen
Session.Item("formulaire") = Request.Form
Server.Transfer("validation.aspx", True)
Case "formulaire"
' het formulier wordt weergegeven met waarden uit de sessie
Context.Items("formulaire") = Session.Item("formulaire")
Server.Transfer("formulaire.aspx", True)
Case Else
' het vooraf ingevulde formulier wordt weergegeven
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
End Select
End Sub
Private Function initForm() As NameValueCollection
' het formulier wordt geïnitialiseerd
Dim form As New NameValueCollection
form.Set("rdMarie", "non")
form.Set("C2", "deux")
form.Set("txtSaisie", "qqs mots")
form.Set("txtMdp", "ceciestsecret")
form.Set("areasaisie", "ligne1" + ControlChars.CrLf + "ligne2" + ControlChars.CrLf)
form.Set("cmbValeurs", "2")
form.Set("lstSimple", "1")
form.Set("lstMultiple", "1")
form.Add("lstMultiple", "3")
Return form
End Function
End Class
De structuur van de eerder besproken applicatiecontroller komt in essentie overeen, met de volgende verschillen:
- de controller voert zijn taken uit in de procedure [Form_Load]
- in het geval van de actie [validation] worden de formulierwaarden uit [Request.Form] opgeslagen in de sessie die gekoppeld is aan de sleutel "formulier". Vervolgens wordt de uitvoering overgedragen aan de pagina [validation.aspx], die deze waarden weergeeft.
- Voor de overige acties wordt de uitvoering in alle gevallen doorgestuurd naar de pagina [formulaire.aspx]. Deze pagina verwacht in haar context een sleutel „formulier” die gekoppeld zal zijn aan een object van het type [Request.form] of c.a.d, of van het type [NameValueCollection]. Dit object moet de verzameling waarden van de formuliervelden bevatten.
- Indien de actie [init] is of een niet-herkende actie, wordt de verzameling waarden willekeurig samengesteld door de functie [initForm].
- Als de actie [formulaire] is, is deze verzameling de verzameling [Request.Form] die door de actie [validation] in de sessie was geplaatst
5.5.3. Het nieuwe formulier
Omdat de applicatie niet langer dezelfde inhoud in het formulier weergeeft, moet dit dynamisch worden gegenereerd. De nieuwe pagina [formulaire.aspx] ziet er als volgt uit:
<%@ Page src="formulaire.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="formulaire" %>
<HTML>
<HEAD>
<title>Formulaire</title>
<script language="javascript">
function effacer(){
alert("Vous avez cliqué sur le bouton [Effacer]");
}
function raz(liste){
liste.selectedIndex=-1
}
</script>
</HEAD>
<body>
<p>
Gestion d'un formulaire
</p>
<hr>
<form name="formulaire" method="post" action="main.aspx?action=validation">
<table border="1">
<tr>
<td>
Etes-vous marié(e)</td>
<td>
<p align="center">
<INPUT type="radio" value="oui" name="rdMarie" <%=rdouichecked%>>Oui
<INPUT type="radio" value="non" name="rdMarie" <%=rdnonchecked%>>Non
</p>
</td>
</tr>
<TR>
<TD>Cases à cocher
</TD>
<TD>
<P align="center">
<INPUT type="checkbox" value="un" name="C1" <%=c1checked%>>1
<INPUT type="checkbox" value="deux" name="C2" <%=c2checked%>>2
<INPUT type="checkbox" value="trois" name="C3" <%=c3checked%>>3
</P>
</TD>
</TR>
<TR>
<TD>Champ de saisie</TD>
<TD>
<P align="center">
<INPUT type="text" maxLength="30" value="<%=txtSaisie%>" name="txtSaisie">
</P>
</TD>
</TR>
<tr>
<td>
Mot de passe</td>
<td>
<p align="center">
<input type="password" maxlength="12" size="12" value="<%=txtMdp%>" name="txtMdp">
</p>
</td>
</tr>
<tr>
<td>
Boîte de saisie</td>
<td>
<textarea name="areaSaisie"><%=areaSaisie%></textarea>
</td>
</tr>
<tr>
<td>
ComboBox</td>
<td>
<select name="cmbValeurs">
<%=cmbValeursOptions%>
</select>
</td>
</tr>
<tr>
<td>
Liste à choix simple</td>
<td>
<select size="3" name="lstSimple">
<%=lstSimpleOptions%>
</select>
<INPUT type="button" value="Raz" name="btnRazSimple" onclick="raz(lstSimple)">
</td>
</tr>
<tr>
<td>
Liste à choix multiple</td>
<td>
<select multiple size="3" name="lstMultiple">
<%=lstMultipleOptions%>
</select>
<INPUT type="button" value="Raz" name="btnRazMultiple" onclick="raz(lstMultiple)">
</td>
</tr>
<tr>
<td>
Bouton simple</td>
<td>
<p align="center">
<input onclick="effacer()" type="button" value="Effacer" name="btnEffacer">
</p>
</td>
</tr>
<tr>
<td>
Bouton submit</td>
<td>
<p align="center">
<input type="submit" value="Envoyer" name="btnEnvoyer">
</p>
</td>
</tr>
<tr>
<td>
Bouton reset</td>
<td>
<p align="center">
<input type="reset" value="Rétablir" name="btnRetablir" runat="server">
</p>
</td>
</tr>
</table>
<input type="hidden" name="secret" value="uneValeur">
</form>
</body>
</HTML>
Laten we de dynamische variabelen bespreken die in de code HTML voorkomen:
variabele | rol |
heeft de waarde "checked" als de keuzeknop [oui] moet worden aangevinkt, anders de waarde "" | |
hetzelfde geldt voor de keuzeknop [non] | |
hetzelfde geldt voor het selectievakje [C1] | |
idem voor het selectievakje [C2] | |
hetzelfde geldt voor het selectievakje [C3] | |
de tekst die in het veld [txtSaisie] moet worden geplaatst | |
de tekst die in het veld [txtMdp] moet worden geplaatst | |
de tekst die in het veld [areaSaisie] moet worden geplaatst | |
de tekst HTML van de opties in de keuzelijst [cmbValeurs] | |
de tekst HTML van de opties in de keuzelijst [lstSimple] | |
de tekst HTML van de opties in de keuzelijst [lstMultiple] | |
De waarden van deze variabelen worden berekend door de controller van de pagina [formulaire.aspx.vb]:
Imports Microsoft.VisualBasic
Imports System.Collections.Specialized
Public Class formulaire
Inherits System.Web.UI.Page
' vaste velden van het formulier
Private libellésCmbValeurs() As String = {"choix1", "choix2", "choix3"}
Private valeursCmbValeurs() As String = {"1", "2", "3"}
Private libellésLstSimple() As String = {"liste1", "liste2", "liste3"}
Private valeursLstSimple() As String = {"1", "2", "3"}
Private libellésLstMultiple() As String = {"multiple1", "multiple2", "multiple3", "multiple4", "multiple5"}
Private valeursLstMultiple() As String = {"1", "2", "3", "4", "5"}
' dynamische velden van het formulier
Protected rdouichecked As String
Protected rdnonchecked As String
Protected c1checked As String
Protected c2checked As String
Protected c3checked As String
Protected txtSaisie As String
Protected txtMdp As String
Protected areaSaisie As String
Protected cmbValeursOptions As String
Protected lstSimpleOptions As String
Protected lstMultipleOptions As String
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' de vorige aanvraag wordt uit de sessie opgehaald
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
' de weer te geven pagina wordt voorbereid
' keuzerondjes
rdouichecked = ""
rdnonchecked = "checked"
If isEqual(form("rdMarie"), "oui") Then
rdouichecked = "checked"
rdnonchecked = ""
End If
' selectievakjes
c1checked = ""
If isEqual(form("C1"), "un") Then c1checked = "checked"
c2checked = ""
If isEqual(form("C2"), "deux") Then c2checked = "checked"
c3checked = ""
If isEqual(form("C3"), "trois") Then c3checked = "checked"
' invoervelden
txtSaisie = ""
If Not form("txtSaisie") Is Nothing Then txtSaisie = form("txtSaisie").ToString
txtMdp = ""
If Not form("txtMdp") Is Nothing Then txtMdp = form("txtMdp").ToString
areaSaisie = ""
If Not form("areaSaisie") Is Nothing Then areaSaisie = form("areaSaisie").ToString
' lijsten
Dim sélections() As String = {}
If Not form("cmbValeurs") Is Nothing Then sélections = form.GetValues("cmbValeurs")
cmbValeursOptions = getOptions(valeursCmbValeurs, libellésCmbValeurs, sélections)
sélections = New String() {}
If Not form("lstSimple") Is Nothing Then sélections = form.GetValues("lstSimple")
lstSimpleOptions = getOptions(valeursLstSimple, libellésLstSimple, sélections)
sélections = New String() {}
If Not form("lstMultiple") Is Nothing Then sélections = form.GetValues("lstMultiple")
lstMultipleOptions = getOptions(valeursLstMultiple, libellésLstMultiple, sélections)
End Sub
Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
' geeft de code HTML weer van de opties van een <select>-tag
' waarden: tabel met de waarden van de opties van de tag
' labels: tabel met de labels van de opties van de tag
' selecties: te selecteren opties
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' de lijst met optiewaarden wordt doorlopen
For iValeur = 0 To valeurs.Length - 1
' wordt gecontroleerd of de huidige waarde moet worden geselecteerd
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' de code HTML van de optie wordt opgenomen
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' het resultaat wordt weergegeven
Return toString
End Function
Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
' geeft ‘waar’ terug als het veld gelijk is aan de waarde
If champ Is Nothing OrElse champ.ToString <> valeur Then
Return false
Else
Return true
End If
end function
End Class
Wanneer de pagina [formulaire.aspx] wordt uitgevoerd, vindt deze in zijn context een 'formulier'-sleutel die gekoppeld is aan de verzameling waarden van de velden die moeten worden weergegeven.
' de vorige query uit de sessie ophalen
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
Men kan zich afvragen waarom wordt gecontroleerd of [Context.Items("formulaire")] bestaat. De controller wijst immers in alle gevallen een waarde toe aan dit object. Niets belet de client echter om de pagina [formulaire.aspx] rechtstreeks op te vragen, zonder via de controller te gaan. Als dat het geval zou zijn, zou de bovenstaande code met een lege verzameling waarden werken, maar er zou geen "crash" optreden.
De code doorloopt de verzameling waarden die hij heeft ontvangen om alle dynamische variabelen te berekenen voor de bijbehorende pagina HTML. Hoewel de code lang is, is hij niet bijzonder ingewikkeld en laten we het aan de lezer over om zich erin te verdiepen, om deze uitleg niet te zwaar te maken. We zullen echter wel stilstaan bij de manier waarop de code HTML wordt gegenereerd uit de drie lijsten van het type [select]. Deze code wordt gegenereerd door de volgende functie:
Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
' geeft de code HTML van de opties van een <select>-tag weer
' waarden: array met de waarden van de opties van de tag
' labels: array met de labels van de opties van de tag
' selecties: te selecteren opties
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' de lijst met optiewaarden wordt doorlopen
For iValeur = 0 To valeurs.Length - 1
' wordt gecontroleerd of de huidige waarde moet worden geselecteerd
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' de code HTML van de optie wordt opgenomen
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' het resultaat wordt weergegeven
Return toString
End Function
Ter herinnering: de opties van een <select>-tag komen overeen met de volgende code HTML:
Voor elke optie moet er dus drie gegevens worden gegenereerd:
- de waarde van de optie in het attribuut [value]
- de tekst van de optie tussen de tags <option> en </option>
- het trefwoord [selected] als de optie in de lijst moet worden geselecteerd
Om deze drie gegevens voor elke optie te genereren, ontvangt de functie [getOptions] drie waarden:
- de tabel met de waarden van de opties in [valeurs]
- de tabel met de teksten van de opties in [libelles]
- de tabel met de te selecteren waarden in [sélections]
5.5.4. De validatiepagina
De validatiepagina blijft ongewijzigd:
[validation.aspx]
<%@ Page src="validation.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="validation" %>
<HTML>
<HEAD>
<title>validation</title>
</HEAD>
<body>
<P>Valeurs saisies</P>
<HR width="100%" SIZE="1">
<TABLE id="Table1" cellSpacing="1" cellPadding="1" width="300" border="1">
<TR>
<TD width="84">rdMarie</TD>
<TD><% =rdMarie%></TD>
</TR>
<TR>
<TD width="84">C1</TD>
<TD><%=C1%></TD>
</TR>
<TR>
<TD width="84">C2</TD>
<TD><%=C2%></TD>
</TR>
<TR>
<TD width="84">C3</TD>
<TD><%=C3%></TD>
</TR>
<TR>
<TD width="84">txtSaisie</TD>
<TD><%=txtSaisie%></TD>
</TR>
<TR>
<TD width="84">txtMdp</TD>
<TD><%=txtMdp%></TD>
</TR>
<TR>
<TD width="84">areaSaisie</TD>
<TD><%=areaSaisie%></TD>
</TR>
<TR>
<TD width="84">cmbValeurs</TD>
<TD><%=cmbValeurs%></TD>
</TR>
<TR>
<TD width="84">lstSimple</TD>
<TD><%=lstSimple%></TD>
</TR>
<TR>
<TD width="84">lstMultiple</TD>
<TD><%=lstMultiple%></TD>
</TR>
<TR>
<TD width="84">secret</TD>
<TD><%=secret%></TD>
</TR>
</TABLE>
<P>
<a href="main.aspx?action=formulaire">Retour au formulaire</a>
</P>
</body>
</HTML>
[validation.aspx.vb]
Imports Microsoft.VisualBasic
Imports System.Text.RegularExpressions
Public Class validation
Inherits System.Web.UI.Page
Protected rdMarie As String
Protected C1 As String
Protected C2 As String
Protected C3 As String
Protected txtSaisie As String
Protected txtMdp As String
Protected areaSaisie As String
Protected cmbValeurs As String
Protected lstSimple As String
Protected lstMultiple As String
Protected secret As String
Protected delimiteur As New Regex("\r\n")
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'de verzonden parameters worden opgehaald
rdMarie = getValue("rdMarie")
C1 = getValue("C1")
C2 = getValue("C2")
C3 = getValue("C3")
txtSaisie = getValue("txtSaisie")
txtMdp = getValue("txtMdp")
areaSaisie = String.Join(",", delimiteur.Split(getValue("areaSaisie")))
cmbValeurs = getValue("cmbValeurs")
lstSimple = getValue("lstSimple")
lstMultiple = getValue("lstMultiple")
secret = getValue("secret")
' we slaan ze op in de sessie
'Session("formulier") = Request.Form
End Sub
Private Function getValue(ByVal champ As String) As String
' haalt de waarde op van het veld [champ] uit de verzonden verzoek
' wat dan?
If Request.Form(champ) Is Nothing Then Return ""
' hiermee worden de waarden van het veld opgehaald
Dim valeurs() As String = Request.Form.GetValues(champ)
Dim valeur As String = ""
Dim i As Integer
For i = 0 To valeurs.Length - 1
valeur += "[" + valeurs(i) + "]"
Next
Return valeur
End Function
End Class
5.5.5. De tests
De bestanden [main.aspx, main.aspx.vb,formulaire.aspx,formulaire.aspx.vb, validation.aspx, validation.aspx.vb] worden in <application-path> geplaatst en Casini wordt gestart met de parameters (<application-path>,/mvcform3). Vervolgens roepen we de URL [http://localhost/mvcform3/main.aspx] op. We krijgen het vooraf geïnitialiseerde formulier te zien:

We vullen het formulier als volgt in:

We gebruiken de bovenstaande knop [Envoyer]. We krijgen het volgende antwoord van de server:

We gebruiken de bovenstaande link [Retour au formulaire] om terug te keren naar het formulier. We krijgen het volgende nieuwe antwoord:

We zien inderdaad het formulier terug zoals we het hebben verzonden.
5.5.6. Conclusie
Het voorgaande voorbeeld heeft aangetoond dat het mogelijk is om de status van een pagina te behouden tijdens de verzoek-antwoordcycli tussen de client en de server. Dit is echter geen eenvoudige opgave. In een later hoofdstuk zullen we zien dat het met ASP.NET mogelijk is om de server zelf de status van een pagina te laten herstellen.



