Skip to content

5. Управління користувацьким інтерфейсом

5.1. Introduction

У веб-взаємодії «клієнт-сервер» клієнт передає інформацію на сервер у вигляді ланцюжка параметрів [param1=val1&param2=val2&...]. У наших попередніх прикладах ми найчастіше створювали цей ланцюжок вручну, використовуючи URL-адреси у форматі [http://localhost/appli? param1=val1&param2=val2&...]. Насправді інформація, яку клієнт передає серверу, походить із форм, заповнених користувачем. У цьому розділі ми розглянемо, як їх створювати. Ми також познайомимося з інструментом WebMatrix, який дозволить нам проектувати користувацькі інтерфейси. Процес встановлення цього інструменту описано в додатках.

5.2. Мова HTML

5.2.1. Приклад

Розглянемо наступний приклад, створений за допомогою [Web Matrix], який містить:

  • таблицю
  • зображення
  • посилання

Image

Запустимо [WebMatrix], а потім виберемо опцію [File/New File]:

Image

Ми вирішили створити сторінку HTML. Наведені вище дані створять файл [d:\data\devel\aspnet\chap4\exemple1\exemple1.htm]. [WebMatrix] пропонує два варіанти редагування цього файлу: режим [Design] та режим [HTML]:

Image

Режим [Design] дозволяє використовувати палітру компонентів HTML, запропоновану [WebMatrix]:

Image

Щоб вставити елемент із цієї палітри, достатньо двічі клацнути на ньому, а потім розмістити його у вікні [Design]. Режим [HTML] дозволяє створювати документ HTML за допомогою текстового редактора. Для цього необхідно знати синтаксис мови HTML. На вкладці [HTML] було згенеровано каркас документа:

Image

Вікно [HTML] дуже корисне для тих, хто не знає мови HTML. Користувач створює свій документ у вікні [Design] і перевіряє код HTML, згенерований у вікні [HTML]. Таким чином користувач поступово опановує HTML і досить швидко може працювати виключно з текстовим редактором без допомоги режиму [Design]. Тепер ми покажемо, як створити документ HTML, представлений на початку цього розділу. Ми працюємо у вікні [Design]. Спочатку ми вводимо безпосередньо перший рядок тексту:

Image

  • додаємо компонент [Horizontal Rule] з палітри компонентів:

Image

  • додаємо компонент [Table]:

Image

  • поміщаємо курсор у третій рядок таблиці, щоб видалити його за допомогою опції [HTML/Edit Table/Delete Table Row]. Потім вводимо потрібний текст у кожну комірку:

Image

  • ми розміщуємо курсор в одній із комірок таблиці та переглядаємо її властивості. Вікно властивостей відображається внизу праворуч робочого середовища:

Image

  • клітинка представлена тегом HTML <TD>. Отже, нам показуються властивості тегу <TD>. Ми звертаємо увагу на таблицю, яка є об’єктом, що охоплює клітинку. Ми клацаємо на випадаючому списку (click to see parent HTML elements) вище, щоб вибрати об’єкт <TABLE>:

Image

  • об’єкт <TABLE> має властивість [border], яка визначає ширину межі навколо комірок таблиці. Тут ми вибираємо border=1.

Image

  • тепер редагуємо атрибути об’єкта <TD> комірки (1,2), щоб встановити значення align=Center та width=200 (пікселів). Текст буде вирівняно по центру в комірці (align=center), а її ширина становитиме 200 пікселів. Щоб побачити зміни, іноді доводиться вибрати вкладку [HTML], а потім повернутися до вкладки [Design]:

Image

  • тепер розмістимо текст, що передує зображенню:

Image

  • потім зображення, двічі клацнувши на компоненті [image] у палітрі:

Image

  • вибираємо зображення, щоб редагувати його властивості:

Image

  • у атрибуті [src] вводимо ім’я файлу, що містить зображення, у даному випадку [univ01.gif]:

Image

  • вводимо текст, що передує посиланню:

Image

  • перетворюємо текст [ici] на посилання на URL-адресу [http://istia.univ-angers.fr]. Для цього виділяємо його, а потім вибираємо опцію [HTML/Insert Hyperlink]:

Image

  • отримуємо такий результат:

Image

  • ми майже досягли мети. Давайте подивимося на код HTML, згенерований у вкладці [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>

Нам залишилося доопрацювати кілька деталей. Перш за все, ми хотіли б надати назву нашому документу. [WebMatrix] не дозволяє зробити це в режимі [Design]. На вкладці [HTML] замінюємо послідовність <head>..</head> на таку:

<head>
    <title>HTML1</title>
</head>

Крім того, ми хотіли б, щоб текст [Le langage HTML - 1] відображався більшим шрифтом. Послідовність <Hi>текст</Hi> дозволяє задати розмір тексту, де i може приймати значення від 1 до 6 — від найбільшого до найменшого. У цьому випадку ми виберемо H2. Послідовність

    <p>
        Le langage HTML - 1 
    </p>

перетворюється на:

<h2>Le langage HTML - 1</h2>

Вікно [Design] відображає наші зміни:

Image

Залишилося лише провести тестування за допомогою опції [View/Start] або [F5]. Опція [WebMatrix] вимагає введення деяких даних для запуску веб-сервера [Cassini]:

Image

Ми можемо прийняти значення, запропоновані за замовчуванням. Сервер [Cassini] запущено, і наша сторінка відображається у браузері:

Image

З цікавості ми можемо перевірити, з якими параметрами було запущено [Cassini]:

Image

Ми розглянули основи створення сторінки HTML за допомогою [WebMatrix]. Пропонуємо читачеві створити інші сторінки HTML і щоразу перевіряти згенерований код HTML. Поступово читач зможе створювати сторінки без допомоги режиму [Design]. Документ HTML має такий загальний вигляд:

<html>
    <head>
        <title>Un titre</title>
        ...
    </head>
    <body attributs>
        ...
    </body>
</html>

Весь документ обмежений тегами <html>...</html>. Він складається з двох частин:

<head>...</head>: це невидима частина документа. Вона надає інформацію браузеру, який буде відображати документ. У ній часто зустрічається тег <title>...</title>, який визначає текст, що відображатиметься у рядку заголовка браузера. Також тут можуть бути інші теги, зокрема ті, що визначають ключові слова документа, які згодом використовуються пошуковими системами. У цій частині також можуть міститися скрипти, найчастіше написані на JavaScript або VBScript, які будуть виконуватися браузером.

<body атрибути>...</body>: це частина, яка відображатиметься браузером. Теги HTML, що містяться в цій частині, вказують браузеру «бажаний» візуальний вигляд документа. Кожен браузер інтерпретує ці теги по-своєму. Тому два браузери можуть по-різному відображати один і той самий веб-документ. Зазвичай це є однією з головних проблем веб-дизайнерів.

Код HTML попереднього документа був таким:

<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>
Елемент
тегів та приклади HTML
titre du document
<title>HTML1</title>
HTML1 з’явиться в рядку заголовка браузера, який відображатиме документ
barre horizontale
<hr>: відображає горизонтальну лінію
tableau
<атрибути таблиці>....</table>: для визначення таблиці
<tr атрибути>...</tr>: для визначення рядка
<td атрибути>...</td>: для визначення комірки
приклади:
<table border="1">...</table>: атрибут border визначає товщину межі таблиці
<td align="center" width="200">комірка(1,2)</td>: визначає комірку, вміст якої буде cellule(1,2). Цей вміст буде вирівняно по горизонталі (align="center"). Ширина комірки становитиме 200 пікселів (width="200")
image
<img src="univ01.gif" />: визначає зображення, вихідний файл якого — univ01.gif — знаходиться на веб-сервері (src="univ01.gif"). Це посилання міститься у веб-документі, отриманому за допомогою URL http://localhost/exemple1.htm. Отже, браузер звернеться до URL http://localhost/univ01.gif, щоб отримати зображення, на яке тут є посилання.
lien
<a href="http://istia.univ-angers.fr">тут</a>: робить текст ici посиланням на URL http://istia.univ-angers.fr.

З цього простого прикладу видно, що для побудови всього документа браузер повинен надіслати два запити на сервер:

http://localhost/exemple1.htm, щоб отримати вихідний код HTML документа

http://localhost/univ01.gif — для отримання зображення univ01.gif

5.2.2. Створення форми

Форма HTML призначена для того, щоб представити користувачеві сторінку введення інформації, аналогічну формам введення, з якими можна зустрітися в Windows. Форма введення надсилається браузеру у вигляді документа HTML. Браузер відобразить форму користувачеві, який заповнить її та підтвердить натисканням відповідної кнопки. Після цього браузер передасть введені значення на сервер для обробки. Як ми побачимо, він надсилає на сервер не всю форму, а лише введені значення. Наступний приклад демонструє веб-форму, також створену за допомогою WebMatrix:

Image

Код HTML, згенерований [WebMatrix], має такий вигляд:


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

Відповідність візуального елемента <--> тегу HTML така:

Перевірка
тег HTML
formulaire
<form name="formulaire" method="post">
champ de saisie
<input type="text" maxlength="30" value="кілька слів" name="txtSaisie" />
champ de saisie cachée
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
champ de saisie multilignes
<textarea name="areaSaisie">рядок1
рядок 2</textarea>
boutons radio
<input type="radio" value="так" name="rdMarie" />Так
<input type="radio" checked value="ні" name="rdMarie" />Ні
cases à cocher
<input type="checkbox" value="один" name="C1" />1
<input type="checkbox" checked value="два" name="C2" />2
<input type="checkbox" value="три" name="C3" />3
Combo
<select name="cmbValeurs">
<option value="1">варіант1</option>
<option value="2" selected>варіант 2</option>
<option value="3">варіант 3</option>
</select>
liste à sélection unique
<select size="3" name="lstSimple">
<option value="1" selected>список1</option>
<option value="2">список2</option>
<option value="3">список3</option>
<option value="4">список4</option>
<option value="5">список5</option>
</select>
liste à sélection multiple
<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>
champ caché
<input type="hidden" name="secret" value="uneValeur" />
bouton de type submit
<input type="submit" value="Надіслати" name="btnEnvoyer" />
bouton de type reset
<input type="reset" value="Скинути" name="btnRetablir" runat="server" />
bouton de type button
<input onclick="effacer()" type="button" value="Очистити" name="btnEffacer" />

Давайте розглянемо ці різні елементи управління.

5.2.2.1. Форма

formulaire
<form name="formulaire" method="post">
balise HTML
<form name="..." method="..." action="...">...</form>
attributs
name="frmexemple": ім'я форми
method="..." : метод, який використовує браузер для надсилання на веб-сервер значень, зібраних у формі
action="..." : URL, на яку будуть надіслані значення, зібрані у формі.
Веб-форма оточена тегами <form>...</form>. Форма може мати ім’я (name="xx"). Це стосується всіх елементів управління, які можна знайти у формі. Це ім’я є корисним, якщо веб-документ містить скрипти, які повинні посилатися на елементи форми. Мета форми — зібрати інформацію, введену користувачем за допомогою клавіатури/миші, та надіслати її на веб-сервер URL. Який саме? Той, що вказаний в атрибуті action="URL". Якщо цей атрибут відсутній, інформація буде надіслана на сервер, на якому розміщений документ, у якому знаходиться форма. Як веб-клієнт передає інформацію (ту, що міститься у формі) на веб-сервер? Ми вже детально розглядали це. Він може використовувати два різні методи, які називаються POST та GET. Атрибут method="méthode", у якому метод дорівнює GET або POST, тегу <form> вказує браузеру, який метод слід використовувати для надсилання інформації, зібраної у формі, на URL, вказаний атрибутом action="URL". Якщо атрибут method не вказано, за замовчуванням використовується метод GET.

5.2.2.2. Поле введення

Image

champ de saisie
<input type="text" maxlength="30" value="кілька слів" name="txtSaisie" />
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
balise HTML
<input type="..." name="..." size=".." value="..">
Тег input використовується для різних елементів управління. Саме атрибут type дозволяє розрізняти ці різні елементи управління між собою.
attributs
type="text": вказує, що це поле введення
type="password": символи у полі введення замінюються на символи *. Це єдина відмінність від звичайного поля введення. Цей тип елемента управління підходить для введення паролів.
size="12": кількість символів, що відображаються у полі — не обмежує введення більшої кількості символів
maxlength="30": встановлює максимальну кількість символів на 30 — браузер відповідає за дотримання цього атрибута
name="txtSaisie": ім’я елемента управління
value="кілька слів": текст, який відображатиметься у полі введення.

5.2.2.3. Багаторядкове поле введення

Image

champ de saisie multilignes
<textarea name="areaSaisie">рядок1
рядок 2</textarea>
balise HTML
<textarea ...>текст</textarea>
відображає багаторядковий поле введення, яке спочатку містить текст
attributs
rows="2": кількість рядків
cols="'20" : кількість стовпців
name="areaSaisie": ім'я елемента управління

5.2.2.4. Радіо-кнопки

Image

boutons radio
<input type="radio" value="так" name="rdMarie" />Так
<input type="radio" checked value="ні" name="rdMarie" />Ні
balise HTML
<input type="radio" атрибут2="значення2" ..../>текст
відображає перемикач із текстом поруч.
attributs
name="rdMarie" : ім'я елемента управління. Перемикачі з однаковим ім'ям утворюють групу, елементи якої взаємовиключні: можна вибрати лише один із них.
value="значення": значення, яке присвоюється перемикачу. Не слід плутати це значення з текстом, що відображається поруч із перемикачем. Останній призначений лише для відображення.
checked: якщо цей ключовий параметр присутній, перемикач позначений як вибраний, інакше — ні.

5.2.2.5. Позначки

cases à cocher
<input type="checkbox" value="один" name="C1" />1
<input type="checkbox" checked value="два" name="C2" />2
<input type="checkbox" value="три" name="C3" />3

Image

balise HTML
<input type="checkbox" attribut2="valeur2" ..../>текст
відображає прапорець із текстом поруч.
attributs
name="C1": ім'я елемента управління. Поля для позначення можуть мати однакове ім'я або ні. Поля з однаковим ім'ям утворюють групу пов'язаних полів.
value="значення": значення, присвоєне прапорцю. Не слід плутати це значення з текстом, що відображається поруч із перемикачем. Останній призначений лише для відображення.
checked: якщо цей ключовий параметр присутній, перемикач позначений, інакше — ні.

5.2.2.6. Список, що розгортається (комбо)

Combo
<select name="cmbValeurs">
<option value="1">варіант1</option>
<option value="2" selected>варіант 2</option>
<option value="3">варіант 3</option>
</select>

Image

balise HTML
<select size=".." name="..">
<option [selected="selected"] [value="valeur"]>текст</option>
...
</select>
відображає у списку тексти, що містяться між тегами <option>...</option>
attributs
name="cmbValeurs": ім'я елемента управління.
size="1": кількість видимих елементів списку. size="1" перетворює список на комбінований список. Це значення за замовчуванням, якщо атрибут [size] відсутній.
selected="selected": якщо цей атрибут присутній для елемента списку, він відображається у списку як вибраний. У нашому прикладі вище елемент списку choix2 відображається як вибраний елемент комбінованого списку, коли той з’являється на екрані вперше.
value="значення": встановлює значення, яке буде надіслано на сервер, якщо елемент вибрано. Якщо цей атрибут відсутній, на сервер надсилається текст, пов’язаний із цим елементом.

5.2.2.7. Список з одним вибором

liste à sélection unique
<select size="3" name="lstSimple">
<option value="1" selected>список1</option>
<option value="2">список2</option>
<option value="3">список3</option>
<option value="4">список4</option>
<option value="5">список5</option>
</select>

Image

balise HTML
<select size=".." name="..">
<option [selected] [value="valeur"]>...</option>
...
</select>
відображає у списку тексти, що містяться між тегами <option>...</option>
attributs
ті самі, що й для випадаючого списку, який відображає лише один елемент. Цей елемент управління відрізняється від попереднього випадаючого списку лише атрибутом size>1.

5.2.2.8. Список із можливістю множинного вибору

liste à sélection multiple
<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>

Image

balise HTML
<select size=".." name=".." multiple>
<option [selected] ] [value="valeur"]>...</option>
...
</select>
відображає у списку тексти, що містяться між тегами <option>...</option>
attributs
multiple: дозволяє вибрати кілька елементів зі списку. У наведеному вище прикладі вибрано обидва елементи: liste1 та liste3.

5.2.2.9. Кнопка типу button

bouton de type button
<input onclick="effacer()" type="button" value="Стерти" name="btnEffacer" />

Image

balise HTML
<input type="button" value="..." name="..." onclick="effacer()" ....>
attributs
type="button": визначає елемент управління «кнопка». Існують ще два типи кнопок: submit та reset.
value="Очистити": текст, що відображається на кнопці
onclick="функція()" : дозволяє визначити функцію, яка має виконуватися, коли користувач натискає на кнопку. Ця функція є частиною скриптів, визначених у відображеному веб-документі. Наведений вище синтаксис відповідає синтаксису javascript. Якщо скрипти написані на VBScript, слід вказати onclick="функція" без дужок. Синтаксис залишається таким самим, якщо потрібно передати параметри до функції: onclick="функція(val1, val2,...)"
У нашому прикладі клік на кнопку Effacer викликає таку функцію JavaScript effacer:

        <script language="javascript">
        function effacer(){
            alert("Vous avez cliqué sur le bouton [Effacer]");
        }
        </script>
Функція effacer відображає повідомлення:

5.2.2.10. Кнопка типу «submit»

bouton de type submit
<input type="submit" value="Надіслати" name="btnEnvoyer" />

Image

balise HTML
<input type="submit" value="Надіслати" name="btnEnvoyer">
attributs
type="submit": визначає кнопку як кнопку для надсилання даних форми на веб-сервер. Коли клієнт натисне на цю кнопку, браузер надішле дані форми на URL, визначений в атрибуті action тегу <form>, відповідно до методу, визначеного атрибутом method цього ж тегу.
value="Відправити": текст, що відображається на кнопці

5.2.2.11. Кнопка типу «reset»

bouton de type reset
<input type="reset" value="Скинути" name="btnRetablir" runat="server" />

Image

balise HTML
<input type="reset" value="Скинути" name=" btnRetablir ">
attributs
type="reset": визначає кнопку як кнопку скидання форми. Коли клієнт натисне на цю кнопку, браузер поверне форму до того стану, в якому він її отримав.
value="Скинути": текст, що відображається на кнопці

5.2.2.12. Приховане поле

champ caché
<input type="hidden" name="secret" value="uneValeur" />
balise HTML
<input type="hidden" name="..." value="...">
attributs
type="hidden": вказує, що це приховане поле. Приховане поле є частиною форми, але не відображається користувачеві. Однак, якщо користувач попросить свій браузер показати вихідний код, він побачить тег <input type="hidden" value="..."> і, отже, значення прихованого поля.
value="uneValeur": значення прихованого поля.
У чому полягає користь прихованого поля? Воно дозволяє веб-серверу зберігати інформацію під час послідовних запитів клієнта. Розглянемо приклад веб-додатку для покупок. Клієнт купує перший товар art1 у кількості q1 на першій сторінці каталогу, а потім переходить на нову сторінку каталогу. Щоб запам’ятати, що клієнт придбав q1 товарів у кількості art1, сервер може помістити ці дві інформації в приховане поле веб-форми на новій сторінці. На цій новій сторінці клієнт купує товари q2 та art2. Коли дані цієї другої форми будуть надіслані на сервер (submit), сервер отримає не тільки інформацію (q2, art2), а й (q1, art1), яка також є частиною форми як приховане поле, яке користувач не може змінювати. Потім веб-сервер помістить у нове приховане поле дані (q1,art1) та (q2,art2) і надішле нову сторінку каталогу. І так далі.

5.3. Передача значень форми з браузера на веб-сервер

З попереднього розділу ми вже знаємо, як клієнт передає інформацію на сервер. Він робить це за допомогою:

  • запит HTTP GET url?param1=va1&param2=val2&....
  • запит HTT POST url, за яким слідує документ, що містить рядок параметрів param1=va1&param2=val2&....

Браузер використовуватиме один із цих двох методів залежно від того, чи атрибут [method] тегу [form] має значення GET чи POST. Саме це ми й продемонструємо зараз. Сторінка, яку ми розглядали раніше, є статичною. Щоб отримати доступ до заголовків HTTP, надісланих браузером, який запитує цей документ, ми перетворюємо її на динамічну сторінку для веб-сервера .NET (IIS або Cassini). Попередній статичний код розміщується у файлі [formulaire_get.aspx], і його вміст є таким:


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

Наведена вище сторінка презентації пов’язана з контролером [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
        ' зберігає поточну запит у request.txt у папці сторінки
        Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
        Me.Request.SaveAs(requestFileName, True)
    End Sub
End Class

При кожному виклику документа [formulaire_get.aspx] запит клієнта буде збережено у файлі [request.txt] за допомогою процедури Page_Init. Ми вже стикалися з таким режимом роботи, тому не будемо детально коментувати цей контролер.

5.3.1. Метод GET

Проведемо перший тест, у якому в коді HTML документа тег FORM визначено таким чином:


        <form name="formulaire" method="get">

Ми розміщуємо файли [formulaire_get.aspx] та [formulaire_get.aspx.vb] у папці <application-path> і запускаємо сервер Cassini з параметрами (<application-path>,/form2). Викликаємо URL-адресу http://localhost/form2/formulaire_get.aspx:

Image

Браузер щойно надіслав запит, і ми знаємо, що він було збережено у файлі [request.txt]. Давайте подивимося на його вміст:

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

Браузер використав запит HTTP GET для запиту URL-адреси [http://localhost/form2/formulaire_get.aspx]. Це завжди відбувається, коли URL-адреса вказується користувачем. Ми заповнюємо форму наступним чином:

Image

Ми використовуємо кнопку [Envoyer], показану вище. Її код HTML такий:

<form method="get">
    ...
    <input type="submit" value="Envoyer">
    ...
</form>

При натисканні кнопки типу [Submit] браузер надсилає параметри форми (тег <form>) на URL, вказаний в атрибуті [action] тегу <form action="URL">, якщо він існує. Якщо цей атрибут відсутній, параметри форми надсилаються на URL, який вивів форму. Саме так і відбувається в даному випадку. Отже, натискання кнопки [Envoyer] має призвести до надсилання браузером запиту до URL [http://localhost/form2/formulaire_get.aspx] із передачею параметрів форми. Оскільки сторінка [formulaire_get.aspx] запам’ятовує отриманий запит, ми маємо дізнатися, як клієнт передав ці параметри. Спробуємо. Натискаємо кнопку [Envoyer]. Отримуємо таку відповідь від браузера:

Image

Це початкова сторінка, але можна помітити, що значення URL у полі [Adresse] браузера змінилося. Воно стало таким:

http://localhost/form2/formulaire_get.aspx?rdMarie=так&C1=один&C2=два&txtSaisie=програмування+asp.net&txtMdp=unMotDePasse&areaSaisie=основи+0D%0Aвеб-програмування%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Надіслати&secret=uneValeur

Можна побачити, що вибір, зроблений у формі, відображається у URL. Давайте розглянемо вміст файлу [request.txt], який зберіг запит клієнта:

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

Ми бачимо запит HTTP, який досить схожий на той, що спочатку надсилав браузер, коли запитував документ без передачі параметрів. Є дві відмінності:

GET URL HTTP/1.1
Параметри форми були додані після URL документа у вигляді ?param1=val1&param2=val2&...
Referer
за допомогою цього заголовка HTTP клієнт вказує код URL документа, який він переглядав під час надсилання запиту

Давайте детальніше розглянемо, як параметри були передані в запиті GET URL?param1=значення1&param2=значення2&... HTTP/1.1, де parami — це імена елементів управління веб-форми, а valeuri — значення, пов’язані з ними. Нижче наведено таблицю з трьома стовпцями:

  • 1-й стовпець: містить визначення елемента управління HTML із прикладу
  • 2-й стовпець: відображення цього елемента управління в браузері
  • 3-й стовпець: містить значення, яке браузер надсилає на сервер для елемента управління зі 1-го стовпця у тому вигляді, в якому воно міститься у запиті GET з прикладу
елемент управління HTML
зображення до підтвердження
повернуте значення (значення)
<input type="radio" value="oui" name="rdMarie" />Так
<input type="radio" checked
value="ні" name="rdMarie" />Ні
rdMarie=так
- значення атрибута value кнопки
радіо-кнопки, яку вибрав користувач.
<input type="checkbox"
value="un" name="C1" />1
<input type="checkbox"
checked value="два" name="C2" />2
<input type="checkbox"
value="три" name="C3" />3
C1=один
C2=два
- значення атрибутів value полів
, позначених користувачем
<input type="text" maxlength="30" value="деякі
слів" name="txtSaisie" />
txtSaisie=програмування+asp.net
- текст, введений користувачем у поле
введення. Пробіли замінено
знаком +
<input type="password"
maxlength="12" size="12"
value="пароль"
name="txtMdp" />
txtMdp=цеСекрет
- текст, введений користувачем у поле
введення. Фактично введений текст був
"цесекрет". Останній символ було
втрачено, оскільки атрибут
maxlength="12" обмежував кількість
символів до 12.
<textarea name="areaSaisie">
рядок1
рядок2</textarea>
areaSaisie=основи+
la%0D%0A
веб-програмування+
— текст, введений користувачем у поле
введення. %OD%OA — це позначка
кінця рядка. Пробіли були
замінені на знак +
<select name="cmbValeurs">
<option value="1">варіант1
</option>
<option value="2" selected>варіант 2
</option>
<option value="3">варіант 3
</option>
</select>
cmbValeurs=3
- значення, обране користувачем у
списку з одним варіантом вибору
<select size="3"
name="lstSimple">
<option value="1"
selected>список1</option>
<option value="2">список2
</option>
<option value="3">список3
</option>
<option value="4">список4
</option>
<option value="5">список 5
</option>
</select>
lstSimple=3
- значення, обране користувачем у
списку з одним варіантом вибору
<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
- значення, вибрані користувачем у
списку з можливістю множинного вибору
<input type="submit"
value="Надіслати"
name="btnEnvoyer" />
btnEnvoyer=Надіслати
- ім'я та атрибут value кнопки, яка
використовувалася для надсилання даних форми
на сервер
<input type="hidden"
name="secret"
value="uneValeur" />
 
secret=uneValeur
- атрибут value прихованого поля

Можна запитати, що сервер зробив із параметрами, які йому передали. Насправді нічого. Після отримання команди

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

веб-сервер передав параметри до URL у документ [http://localhost/form2/formulaire_get.aspx], c.a.d. у документ, який ми створили спочатку. Ми не писали жодного коду для отримання та обробки параметрів, які надсилає нам клієнт. Тому все відбувається так, ніби запит клієнта був просто таким:

GET http://localhost/form2/formulaire_get.aspx

Саме з цієї причини у відповідь на натискання нашої кнопки [Envoyer] ми отримали ту саму сторінку, що й спочатку при запиті URL [http://localhost/form2/formulaire_get.aspx] без параметрів.

5.3.2. Метод POST

Документ HTML тепер налаштований так, щоб браузер використовував метод POST для надсилання значень форми на веб-сервер. Для цього ми копіюємо файл [formulaire_get.aspx] у [formulaire_post.aspx] і змінюємо лише тег <form> у [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">

Немає необхідності змінювати контролер [formulaire_get.aspx.vb], тому залишаємо його без змін. Запитуємо новий документ через URL [http://localhost/form2/formulaire_post.aspx], заповнюємо форму так само, як для методу GET, і передаємо параметри на сервер за допомогою кнопки [Envoyer]. Ми отримуємо від сервера таку сторінку відповіді:

Image

Отже, ми отримуємо той самий результат, що й у методах GET та c.a.d — початкову сторінку. Можна помітити одну відмінність: у полі [Adresse] браузера передані параметри не відображаються. Тепер розглянемо запит, надісланий клієнтом і збережений у файлі [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

У запиті клієнта HTTP з'являються нові елементи:

POST URL HTTP/1.1
запит GET замінено на запит POST. Параметри більше не містяться в першому рядку запиту. Можна помітити, що тепер вони розміщені після запиту HTTP, після порожнього рядка. Їхнє кодування ідентичне тому, яке вони мали в запиті GET.
Content-Length
кількість «відправлених» символів, c.a.d. Кількість символів, яку веб-сервер повинен прочитати після отримання заголовків HTTP, щоб отримати документ, який надсилає йому клієнт. У даному випадку цим документом є список значень форми.
Content-type
вказує тип документа, який клієнт надішле після заголовків HTTP. Тип [application/x-www-form-urlencoded] вказує, що це документ, який містить значення форми.

Існує два методи передачі даних на веб-сервер: GET та POST. Чи є один із цих методів кращим за інший? Ми бачили, що якщо значення форми надсилалися браузером за допомогою методу GET, браузер відображав у своєму полі Adresse запитуване значення URL у формі URL?param1=val1&param2=val2&.... Це можна розглядати як перевагу або недолік:

  • перевагою, якщо ми хочемо дозволити користувачеві додати цей налаштований URL до своїх улюблених посилань
  • недолік, якщо не хочемо, щоб користувач мав доступ до певної інформації у формі, наприклад, до прихованих полів

Надалі ми будемо використовувати у своїх формах майже виключно метод POST.

5.4. Обробка значень форми на стороні сервера

5.4.1. Огляд прикладу

Тепер, коли ми встановили зв’язок між тегом HTML <form method="GET/POST" ...> та способом, яким браузер надсилає значення форми, ми знаємо, як отримати їх на стороні сервера. Відповідь ми отримали в попередньому розділі:

  • якщо метод тегу <form> дорівнює GET, значення параметрів будуть отримані з колекції [Request.QueryString]
  • якщо метод тегу <form> дорівнює POST, значення «відправлених» параметрів будуть отримані з колекції [Request.Form]. Тут слід зробити уточнення. Тег <form> може за допомогою атрибута [action] вказати цільову URL-адресу GET або POST. Цю URL-адресу цілком можна налаштувати незалежно від того, чи маємо ми GET, чи POST, у формі action="url?param1=val1&param2=val2&..". Ці параметри додаються до тих, що містяться між тегами <form> та </form> і які будуть передані на сервер за допомогою GET або POST. Оскільки вони є частиною цільового URL-адреси, їх можна отримати в колекції [Request.QueryString] незалежно від того, чи маємо ми справу з GET, чи з POST.

Тепер ми напишемо додаток MVC із двома вікнами:

  • перший вигляд — це попередня форма. Назвемо її [vue_formulaire].
  • другий вигляд — це інформаційна сторінка, на якій перелічено значення, введені на першій сторінці. Посилання дозволяє повернутися до форми. Назвемо цей вигляд [vue_confirmation].

Вигляд [vue_formulaire] надсилається користувачеві, який його заповнює та підтверджує. Перед підтвердженням він може виглядати так:

Image

Користувач натискає кнопку [Envoyer], щоб підтвердити введені дані. У відповідь він отримує наступний вигляд [vue_validation]:

Image

5.4.2. Контролер додатка

У попередньому розділі ми бачили, що роль контролера додатка MVC можна доручити файлу [global.asax], через який проходять усі запити клієнтів. Ми вже розглядали додаток MVC, побудований за такою схемою, і тут дотримуємося представленої тоді моделі розробки. Файл [global.asax] матиме такий вигляд:

<%@ Application src="Global.asax.vb" Inherits="Global" %>

Він складається з єдиного рядка, що посилається на контролер, розміщений у файлі [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)
        ' отримуємо дію, яку потрібно виконати
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' виконуємо дію
        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

Принцип роботи контролера такий:

  • він очікує в цільовому URL-адресі рядок параметрів, що містить параметр [action]. Якщо його немає, то система поводиться так, ніби в рядку параметрів був параметр [action=init].
  • Підтримуються лише дві дії:
    • init: клієнту надається попередньо заповнена форма
    • validation: клієнту надається сторінка з підтвердженням введених даних
  • якщо дія не є однією з перерахованих вище, то вважається, ніби в рядку параметрів був параметр [action=init]. Також можна вивести сторінку з повідомленням про помилку.

5.4.3. Обробка дії init

Коли контролер обробляє дію «init», він повинен згенерувати попередньо заповнену форму. Цю роботу виконує сторінка [formulaire.aspx]. Її код такий:


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

Ми бачимо код HTML з форми, яку розглядали раніше, за винятком кількох відмінностей. Код тегу <form> було змінено:


        <form name="formulaire" method="post" action="?action=validation">
  • post: значення, введені користувачем і надіслані на сервер при натисканні кнопки типу [submit], будуть оброблятися методом HTTP POST
  • action: синтаксис action="url" використовується для вказівки URL-адреси, на яку мають бути надіслані значення форми. Ця URL-адреса може містити ланцюжок параметрів у вигляді param1=val1&param2=val2&... Саме це робиться тут, де ми передаємо параметр [action=validation], щоб вказати контролеру, яку дію він повинен виконати. Варто зауважити, що перед цим ланцюжком параметрів не стоїть веб-адреса. Тоді браузер надішле параметри форми на адресу, яка надала йому цю форму. У нашому прикладі, наведеному вище, ця адреса — [http://localhost/mvcform1]. Отже, браузер надішле запит [POST /mvcform1?action=validation] на сервер [localhost].

Були додані кнопки, щоб користувач міг скасувати вибір елементів зі списків [lstSimple] та [lstMultiple]:

Image

Це відображається у вигляді такого коду 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>

Натискання на кнопку [Raz] призводить до скасування виділення всіх елементів списку, з яким вона пов’язана. Розглянемо приклад списку [lstMultiple]. Клік на відповідну кнопку [Raz] призводить до виконання функції JavaScript [raz(lstMultiple)]. Нагадаємо, що код JavaScript документа HTML, який відображається браузером, виконується саме цим браузером, а не сервером. JavaScript — це дуже функціональна мова, яка дозволяє надавати сторінкам динамічний вигляд без втручання сервера. Функція [raz] має такий вигляд:

        function raz(liste){
            liste.selectedIndex=-1
        }

Ця функція приймає параметр у вигляді об’єкта JavaScript, що представляє список HTML. Цей об’єкт має властивості та методи. Однією з його властивостей є [selectedIndex], значенням якої є номер першого вибраного варіанта у списку HTML. Якщо такого елемента немає, значення цього властивості дорівнює -1. І навпаки, присвоєння значення цьому властивості означає вибір нового елемента зі списку HTML, а присвоєння йому значення -1 означає, що жоден елемент не вибрано. Саме це й робиться тут.

Нарешті, слід зауважити, що код представлення [formulaire.aspx] не супроводжується контролером [formulaire.aspx.vb]. Дійсно, у документі HTML немає жодної динамічної частини, згенерованої сервером, тому немає необхідності мати контролер.

5.4.4. Обробка дії «validation»

Коли контролер обробляє дію «validation», він повинен згенерувати сторінку зі списком значень, введених користувачем. Цю роботу виконує сторінка [validation.aspx]. Візуально сторінка виглядає наступним чином:

Image

Її код HTML виглядає так:


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

Динамічні частини <%=variable%> документа обчислюються відповідним контролером [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
        'отримуємо надіслані параметри
        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
        ' отримує значення поля [champ] із надісланого запиту
        ' щось?
        If Request.Form(champ) Is Nothing Then Return ""
        ' отримуємо значення поля або поля
        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

Обчислення значень, що відображаються, виконується у процедурі [Form_Load]. Значення «опублікованого» поля отримується за допомогою функції getValue(C), де C — ім’я поля. Ключові моменти цієї функції такі:

  • якщо C відсутнє у переданому ланцюжку параметрів, то як значення C повертається порожній ланцюжок
  • в іншому випадку отримується масив значень поля C за допомогою [Request.Form.GetValues(C)]. Ці значення об’єднуються в символьний рядок у формі [val1][val2]...[valn], де [vali] — це значення № i поля C

Поле [areaSaisie] обробляється особливим чином. Його значення надсилається браузером у вигляді areaSaisie=рядок1\r\nрядок2\r\n... де \r — це символ з кодом ASCII 13 (повернення каретки), а \n — символ з кодом ASCII 10 (перехід на новий рядок). Отже, функція getValue(areaSaisie) — це рядок «рядок1\r\nрядок2\r\n...». Цей рядок розбивається на рядки за допомогою методу [Regex.Split]. У результаті отримуємо масив рядків {рядок1, рядок2, ...}. Цей масив перетворюється на рядок «рядок1, рядок2, ...» за допомогою методу [String.Join]. Саме цей рядок буде відображатися як значення поля [areaSaisie]. Метою цього прикладу було продемонструвати, як можна отримати окремі рядки поля HTML типу [TextArea].

5.4.5. Тестування

Ми розміщуємо всі файли (global.asax, global.asax.vb, formulaire.aspx, validation.aspx, validation.aspx.vb) у папку <application-path>. Запускаємо сервер Cassini з параметрами (<application-path>,/mvcform1). У папці <application-path> створюємо порожній файл [default.aspx], а потім звертаємося за URL-адресою [http://localhost/mvcform1]. Оскільки [/mvcform1] є віртуальним шляхом до папки, а не до документа, веб-сервер відобразить документ [default.aspx], якщо він існує. Саме тому ми його й створили. Перед його відображенням буде виконано скрипт [global.asax], що в результаті призведе до відображення сторінки [formulaire.aspx]. Саме тому файл [default.aspx] може бути порожнім.

Припустимо, що затверджена форма має такий вигляд:

Image

Натискання кнопки [Envoyer] повертає таку сторінку:

Image

Спочатку звернемо увагу на URL-адресу відповіді: [http://localhost/mvcform1/?action=validation]. Це URL з атрибута [action] тегу <form> форми [formulaire.aspx]:


        <form name="formulaire" method="post" action="?action=validation">

Розглянемо по черзі значення, отримані для різних полів форми:

поле
значення
HTML
коментарі
rdMarie
так
<input type="radio" value="так"
name="rdMarie">Так
<input type="radio" checked
value="ні" name="rdMarie">Ні
отримане значення є атрибутом [value] позначеної кнопки
C1
один
<input type="checkbox"
value="un" name="C1">1
те саме
C2
два
<input type="checkbox"
checked value="два" name="C2">2
те саме
C3
 
<input type="checkbox"
value="три" name="C3">3
Ця кнопка не була відмічена користувачем. Отже, її значення не було надіслано браузером. У коді умова [Request.Form("C3") is Nothing], отже, була істинною.
txtSaisie
Програмування
asp.net
<input type="text"
... name="txtSaisie">
отримане значення — це текст, що міститься у полі введення на момент підтвердження
txtMdp
mdp
<input type="password"
...name="txtMdp">
те саме
areaSaisie
основи
веб-програмування
<textarea name="areaSaisie">
...</textarea>
те саме
cmbValeurs
3
<select name="cmbValeurs">
...
<option value="3">варіант 3</option>
</select>
отримане значення є атрибутом [value] вибраної опції
lstSimple
3
<select size="3" name="lstSimple">
....
<option value="3">список3</option>
...
</select>
те саме
lstMultiple
2 4
<select multiple size="3" name="lstMultiple">
...
<option value="2">multiple2
</option>
...
<option value="4">multiple4
</option>
...
</select>
отримані значення відповідають атрибутам [value] вибраних опцій
secret
uneValeur
<input type="hidden"
name="secret" value="uneValeur">
отримане значення відповідає атрибуту [value] прихованого поля

Тепер розглянемо списки. Припустимо, що на момент перевірки стан форми такий:

Image

  • опція [choix1] вибрана в comboBox
  • у двох інших списках жодна опція не обрана. Для цього були використані кнопки [Raz].

Ось сторінка, яка з’явилася після підтвердження:

Image

Коли в списку не вибрано жодного значення, браузер не надсилає відповідного параметра. Отже, у коді [validation.aspx.vb] вирази [Request.Form("lstSimple")] та [Request.Form("lstMultiple")] дорівнюють константі [Nothing], звідки й випливає результат, показаний вище.

5.5. Збереження стану сторінки

5.5.1. Збереження стану сторінки за допомогою сесії

Ми копіюємо весь попередній додаток у нову папку. На сторінці [validation.aspx] додаємо посилання, яке дозволяє користувачеві повернутися до форми:

Image

Зміни, які потрібно внести на сторінці [validation.aspx], полягають у додаванні посилання:


.....
            <TR>
                <TD width="84">secret</TD>
                <TD><%=secret%></TD>
            </TR>
        </TABLE>
        <P>
            <a href="?action=formulaire">Retour au formulaire</a>
        </P>
    </body>
</HTML>

Атрибут [href] посилання має значення URL-адреси з єдиним параметром [action=formulaire], що дозволяє серверу зрозуміти, що він повинен відобразити форму такою, якою вона була на момент її підтвердження. Отже, існує відмінність від дії [init], яка відображає заздалегідь визначену форму. URL-адреса з параметром [?action=formulaire] насправді не має URL-адреси. Тому вона буде такою самою, як та, що дозволила відобразити сторінку підтвердження. Якщо згадати попереднє дослідження, це URL-адреса каталогу додатка. Отже, запит пройде через контролер. Тепер він повинен обробити дію [formulaire]. Код [global.asax.vb] змінюється наступним чином:


    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' отримуємо дію, яку потрібно виконати
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' виконується дія
        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

У випадку, якщо дія є «формою», достатньо просто передати запит на сторінку [formulaire.aspx]. Відомо, що ця сторінка відображає заздалегідь визначену форму, у якій немає жодних змінних частин. Отже, ця сторінка не може відобразити форму з тими значеннями, які вона мала на момент її підтвердження. Тут ми прагнемо підкреслити саме цей момент. Якщо всі файли додатка розміщено в <application-path>, ми запускаємо Cassini з параметрами (<application-path>,/mvcform2), а потім звертаємося за URL-адресою [http://localhost/mvcform2]. Ми отримуємо таку сторінку (частковий вигляд):

Image

Ми заповнюємо форму наступним чином, а потім підтверджуємо її:

Image

Ми отримуємо таку сторінку підтвердження:

Image

Ми використовуємо посилання [Retour au formulaire], яке є (але не відображається) на сторінці вище. Ми отримуємо таку відповідь від сервера:

Image

Ми бачимо, що:

  • запитана URL-адреса дійсно містить параметр action=formulaire, як і було потрібно
  • відображена форма втратила введені значення.

Ми знаємо, чому не бачимо введених значень. Якщо подивитися на код документа [formulaire.aspx], то можна побачити, що все є статичним, і тому система змушена щоразу відображати одну й ту саму сторінку. Очевидно, що нам потрібно зробити цей код динамічним. Він повинен відображати значення, підтверджені користувачем. Але де їх зберігати?

Нагадаємо «залізне правило» безстатного протоколу HTTP:

  • запитується URL-адреса [http://localhost/mvcform2] — отримується відповідь. Зв’язок TCP-IP між клієнтом і сервером відкривається на початку запиту і закривається після отримання відповіді.
  • користувач вводить, а потім підтверджує дані. Запитується URL-адреса [http://localhost/mvcform2/?action=validation] — отримується відповідь. Між двома партнерами було відкрито, а потім закрито нове з’єднання TCP-IP.
  • Користувач використовує посилання [Retour au formulaire]. Запитується URL-адреса [http://localhost/mvcform2/?action=formulaire] — отримується відповідь. Між двома партнерами знову було відкрито, а потім закрито нове з’єднання TCP-IP.

Цикли «запит-відповідь» є незалежними один від одного, оскільки кожен із них використовує нове з’єднання TCP-IP. Коли клієнтсько-серверний додаток використовує єдине з’єднання TCP-IP для серії обмінів, сервер може ідентифікувати клієнта за його з’єднанням. Таким чином, він може запам’ятати інформацію, яку пов’яже з конкретним з’єднанням, і таким чином відстежувати обміни. Коли обміни відбуваються через різні з’єднання, сервер не може ідентифікувати клієнта за з’єднанням. Потрібен інший спосіб. Один із них ми розглянули в попередньому розділі: механізм сеансу. Він дозволяє циклам «запит-відповідь» зберігати інформацію в об’єкті [Session], доступному для всіх наступних циклів.

Тепер, коли ми маємо додаток MVC із сесією, ми більше не можемо використовувати файл [global.asax] як контролер, як це було показано в попередньому розділі. Роль контролера додатка має виконувати спеціальна сторінка, призначена саме для цього. У даному випадку це буде сторінка [main.aspx]. Ми будемо діяти таким чином:

  • коли користувач підтвердить свої дані (action=validation), контролер [main.aspx.vb] збереже їх у поточній сесії, перш ніж відобразити сторінку підтвердження.
  • коли потрібно буде відобразити форму з введеними значеннями (action=formulaire), контролер [main.aspx.vb] отримає їх із сесії та помістить у контекст перед тим, як відобразити форму.

5.5.2. Новий контролер додатка

Контролер додатка складається з двох файлів [main.aspx, main.aspx.vb]:

[main.aspx]

<%@ Page src="main.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="main" %>

[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
        ' отримуємо дію, яку потрібно виконати
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' виконується дія
        Select Case action
            Case "init"
                ' відображається попередньо заповнена форма
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
            Case "validation"
                ' відображається сторінка підтвердження після збереження значень, відправлених у сесії
                Session.Item("formulaire") = Request.Form
                Server.Transfer("validation.aspx", True)
            Case "formulaire"
                ' відображається форма зі значеннями, отриманими з сесії
                Context.Items("formulaire") = Session.Item("formulaire")
                Server.Transfer("formulaire.aspx", True)
            Case Else
                ' відображається попередньо заповнена форма
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub

    Private Function initForm() As NameValueCollection
        ' ініціалізується форма
        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

Тут ми бачимо суть структури контролера додатка, який ми розглядали раніше, з такими відмінностями:

  • робота контролера здійснюється в процедурі [Form_Load]
  • у разі дії [validation] значення форми, що містяться в [Request.Form], зберігаються в сесії, пов’язаній із ключем «форма». Потім виконання передається на сторінку [validation.aspx], яка відобразить ці значення.
  • Для інших дій виконання в усіх випадках переходить на сторінку [formulaire.aspx]. Ця сторінка очікує у своєму контексті ключ «formulaire», який буде пов’язаний з об’єктом типу [Request.form] або c.a.d, або типу [NameValueCollection]. Цей об’єкт повинен містити набір значень полів форми.
  • у разі, якщо дія має код [init] або є невизнаною, набір значень формується довільно за допомогою функції [initForm].
  • у разі, якщо дія має код [formulaire], цим набором є набір [Request.Form], який був розміщений у сесії дією [validation]

5.5.3. Нова форма

Оскільки додаток більше не відображає той самий вміст у формі, її потрібно генерувати динамічно. Нова сторінка [formulaire.aspx] виглядає так:


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

Прокоментуємо динамічні змінні, що з’являються в коді HTML:

змінна
роль
rdouichecked
матиме значення «checked», якщо потрібно встановити прапорець [oui], і значення «» в іншому випадку
rdnonchecked
те саме стосується перемикача [non]
c1checked
те саме стосується прапорця [C1]
c2checked
те саме для прапорця [C2]
c3checked
те саме стосується прапорця [C3]
txtSaisie
текст, який потрібно ввести в поле [txtSaisie]
txtMdp
текст, який потрібно розмістити в полі [txtMdp]
areaSaisie
текст, який потрібно розмістити в полі [areaSaisie]
cmbValeursOptions
текст HTML з опцій списку вибору [cmbValeurs]
lstSimpleOptions
текст HTML з опцій списку вибору [lstSimple]
lstMultipleOptions
текст HTML з опцій списку вибору [lstMultiple]
  

Значення цих змінних обчислюються контролером сторінки [formulaire.aspx.vb]:


Imports Microsoft.VisualBasic
Imports System.Collections.Specialized

Public Class formulaire
    Inherits System.Web.UI.Page

    ' постійні поля форми
    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"}

    ' динамічні поля форми
    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
        ' отримуємо попередній запит із сесії
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If
        ' підготовка сторінки до відображення
        ' перемикачі
        rdouichecked = ""
        rdnonchecked = "checked"
        If isEqual(form("rdMarie"), "oui") Then
            rdouichecked = "checked"
            rdnonchecked = ""
        End If
        ' прапорці
        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"
        ' поля введення
        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
        ' списки
        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
        ' повертає код HTML опцій тегу <select>
        ' значення: масив значень параметрів тегу
        ' назви: масив назв параметрів тегу
        ' вибори: параметри для вибору
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
        ' проглядаємо список значень параметрів
        For iValeur = 0 To valeurs.Length - 1
            ' перевіряється, чи слід вибрати поточне значення
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
            ' вставляється код HTML опції
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
        ' повертається результат
        Return toString
    End Function

    Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
        ' повертає «true», якщо поле дорівнює значенню
        If champ Is Nothing OrElse champ.ToString <> valeur Then
            Return false
        Else
            Return true
        End If
    end function
End Class

Коли сторінка [formulaire.aspx] починає виконуватися, вона знаходить у своєму контексті ключ «форма», пов'язаний із набором значень полів, які вона має відобразити.


         ' отримуємо попередній запит із сесії
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If

Можна задатися питанням, навіщо перевіряється наявність об’єкта [Context.Items("formulaire")]. Адже контролер у будь-якому разі присвоює цьому об’єкту значення. Однак ніщо не заважає клієнту безпосередньо запросити сторінку [formulaire.aspx], оминаючи контролер. У такому випадку наведений вище код працюватиме з порожньою колекцією значень, але «збою» не відбудеться.

Код обходить отриманий масив значень, щоб обчислити всі динамічні змінні сторінки HTML, яка з ним пов’язана. Хоча цей код і довгий, він не є особливо складним, і ми залишаємо читачеві можливість самостійно вникнути в нього, щоб не перевантажувати це пояснення. Проте ми зупинимося на тому, як генерується код HTML із трьох списків типу [select]. Цей код генерується наступною функцією:

    Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
         ' повертає код HTML з опцій тегу <select>
         ' значення: масив значень параметрів тегу
         ' назви: масив назв параметрів тегу
         ' вибори: параметри для вибору
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
         ' проглядаємо список значень параметрів
        For iValeur = 0 To valeurs.Length - 1
             ' перевіряється, чи слід вибрати поточне значення
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
             ' вставляється код HTML опції
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
         ' повертаємо результат
        Return toString
    End Function

Нагадаємо, що параметри тегу <select> відповідають такому коду HTML:

<option [selected] value="...">texte</option>

Отже, для кожного параметра потрібно згенерувати три елементи інформації:

  • значення параметра в атрибуті [value]
  • текст опції між тегами <option> та </option>
  • ключове слово [selected], якщо опцію потрібно вибрати зі списку

Щоб згенерувати ці три елементи для кожної з опцій, функція [getOptions] отримує три значення:

  1. масив значень опцій у [valeurs]
  2. масив текстів опцій у [libelles]
  3. масив значень для вибору в [sélections]

5.5.4. Сторінка підтвердження

Сторінка перевірки залишається без змін:

[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
        'отримуємо надіслані параметри
        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")
        ' зберігаємо їх у сесії
        'Session("formulaire") = Request.Form
    End Sub

    Private Function getValue(ByVal champ As String) As String
        ' отримуємо значення поля [champ] із відправленого запиту
        ' щось таке?
        If Request.Form(champ) Is Nothing Then Return ""
        ' отримуємо значення поля або полів
        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. Тестування

Файли [main.aspx, main.aspx.vb,formulaire.aspx,formulaire.aspx.vb, validation.aspx, validation.aspx.vb] розміщуються в <application-path>, а Casini запускається з параметрами (<application-path>,/mvcform3). Потім ми звертаємося за URL-адресою [http://localhost/mvcform3/main.aspx]. Ми отримуємо попередньо ініціалізовану форму:

Image

Заповнюємо форму наступним чином:

Image

Натискаємо кнопку [Envoyer], розташовану вище. Отримуємо таку відповідь від сервера:

Image

Ми використовуємо наведене вище посилання [Retour au formulaire], щоб повернутися до форми. Отримуємо таку нову відповідь:

Image

Ми бачимо саме ту форму, яку підтвердили.

5.5.6. Висновок

Попередній приклад показав, що можна зберігати стан сторінки протягом циклів запит-відповідь між клієнтом і сервером. Проте це завдання не є простим. У наступному розділі ми побачимо, що за допомогою ASP.NET можна дозволити серверу самостійно відновлювати стан сторінки.