5. إدارة واجهة المستخدم
5.1. مقدمة
في العلاقة بين العميل والخادم على الويب، يرسل العميل المعلومات إلى الخادم في شكل سلسلة من المعلمات [param1=val1¶m2=val2&...]. في الأمثلة السابقة، كنا نبني هذه السلسلة يدويًا في أغلب الأحيان عن طريق طلب عناوين URL من النوع [http://localhost/appli? param1=val1¶m2=val2&...]. في الواقع، تأتي المعلومات التي يرسلها العميل إلى الخادم من النماذج التي قام المستخدم بملئها. نستكشف في هذا الفصل كيفية إنشاء هذه النماذج. كما نقدم أداة WebMatrix، التي ستسمح لنا بتصميم واجهات المستخدم. يرد وصف تثبيت هذه الأداة في الملاحق.
5.2. لغة HTML
5.2.1. مثال
انظر المثال التالي، الذي تم إنشاؤه باستخدام [Web Matrix]، والذي يعرض:
- جدول
- صورة
- رابط

قم بتشغيل [WebMatrix] واختر خيار [File/New File]:

نختار إنشاء صفحة HTML. ستؤدي المعلومات المذكورة أعلاه إلى إنشاء ملف [d:\data\devel\aspnet\chap4\example1\example1.htm]. يوفر [Web Matrix] طريقتين لتحرير هذا الملف: وضع [Design] ووضع [HTML]:

يتيح لك وضع [التصميم] استخدام لوحة مكونات HTML التي يوفرها [WebMatrix]:

لإدراج عنصر من هذه اللوحة، ما عليك سوى النقر عليه مرتين ثم وضعه في نافذة [التصميم]. يتيح لك وضع [HTML] إنشاء مستند HTML باستخدام محرر نصوص. وهذا يتطلب معرفة بقواعد لغة HTML. في علامة التبويب [HTML]، تم إنشاء هيكل للمستند:

تُعد نافذة [HTML] مفيدة جدًا لمن ليسوا على دراية بلغة HTML. يمكنك إنشاء المستند في نافذة [التصميم] والتحقق من كود HTML الناتج في نافذة [HTML]. وبهذه الطريقة، ستتقن لغة HTML تدريجيًا وستتمكن من العمل بسرعة باستخدام محرر النصوص وحده دون الاعتماد على وضع [التصميم]. سنشرح الآن كيفية إنشاء مستند HTML الموضح في بداية هذا القسم. نحن نعمل في نافذة [التصميم]. أولاً، ندخل السطر الأول من النص مباشرةً:

- نضيف مكون [Horizontal Rule] من لوحة المكونات:

- نضيف مكون [Table]:

- نضع المؤشر في الصف الثالث من الجدول لحذفه باستخدام خيار [HTML/Edit Table/Delete Table Row]. ثم ندخل النص المطلوب في كل خلية:

- نضع المؤشر في إحدى خلايا الجدول ونفحص خصائصها. تظهر نافذة الخصائص في أسفل يمين مساحة العمل:

- يتم تمثيل الخلية بعلامة HTML <TD>. لذلك، يتم عرض خصائص علامة <TD> لنا. نركز على الجدول، وهو كائن يحتوي على الخلية. نضغط على القائمة المنسدلة (اضغط لرؤية عناصر HTML الأصلية) أعلاه لاختيار كائن <TABLE>:

- يحتوي كائن <TABLE> على خاصية [border] التي تحدد عرض الحدود المحيطة بخلايا الجدول. هنا، نحدد border=1.

- سنقوم الآن بتحرير سمات كائن <TD> في الخلية (1،2) لتعيين align=Center و width=200 (بكسل). سيتم توسيط النص في الخلية (align=center)، وسيكون عرض الخلية 200 بكسل. لرؤية التغيير، قد تحتاج إلى تحديد علامة التبويب [HTML] ثم العودة إلى علامة التبويب [Design]:

- الآن نضع النص الذي يسبق الصورة:

- ثم الصورة بالنقر المزدوج على مكون [image] في اللوحة:

- نختار الصورة لتحرير خصائصها:

- في السمة [src]، ندخل اسم الملف الذي يحتوي على الصورة، وهنا [univ01.gif]:

- نضع النص الذي يسبق الرابط:

- نحول النص [هنا] إلى رابط إلى عنوان URL [http://istia.univ-angers.fr]. للقيام بذلك، نحدده ثم نختار الخيار [HTML/إدراج ارتباط تشعبي]:

- نحصل على النتيجة التالية:

- لقد أوشكنا على الانتهاء. دعونا نلقي نظرة على كود 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> بما يلي:
بالإضافة إلى ذلك، نود أن يظهر النص [HTML - 1] بخط أكبر. تتيح لك علامة <Hi>text</Hi> ضبط حجم النص، حيث يتراوح الرقم "i" من 1 إلى 6، من الأكبر إلى الأصغر. هنا، سنستخدم H2. العلامة
تصبح:
تعكس نافذة [Design] التغييرات التي أجريناها:

كل ما تبقى هو اختباره باستخدام خيار [View/Start] أو [F5]. يطلب [WebMatrix] بعض المعلومات لبدء تشغيل خادم الويب [Cassini]:

يمكننا قبول القيم الافتراضية. يتم تشغيل خادم [Cassini] ويتم عرض صفحتنا في المتصفح:

بدافع الفضول، يمكننا التحقق من المعلمات التي تم استخدامها لتشغيل [Cassini]:

لقد تناولنا أساسيات إنشاء صفحة HTML باستخدام [WebMatrix]. ونشجع القراء على إنشاء صفحات HTML أخرى والتحقق من كود HTML الناتج في كل مرة. وبالتدريج، سيتمكنون من إنشاء صفحة دون استخدام وضع [التصميم]. يتكون مستند 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 | علامات HTML وأمثلة |
<title>HTML1</title> سيظهر HTML1 في شريط عنوان المتصفح عند عرض المستند | |
<horizontal> : يعرض خطًا أفقيًا | |
<سمات الجدول>....</table> : لتعريف الجدول <tr attributes>... : لتعريف صف <td attributes>... : لتعريف خلية أمثلة: <table border="1">...: تحدد سمة border سماكة حدود الجدول <td align="center" width="200">cell(1,2) : تحدد خلية سيكون محتواها cell(1,2). سيتم توسيط هذا المحتوى أفقيًا (align="center"). سيكون عرض الخلية 200 بكسل (width="200") | |
<img src="univ01.gif" />: يُحدد صورة ملفها الأصلي هو univ01.gif على خادم الويب (src="univ01.gif"). يقع هذا الرابط في مستند ويب يمكن الوصول إليه عبر عنوان URL http://localhost/exemple1.htm. وبالتالي، سيقوم المتصفح بطلب عنوان URL http://localhost/univ01.gif لاسترداد الصورة المشار إليها هنا. | |
<a href="http://istia.univ-angers.fr">here: يجعل النص "here" بمثابة رابط إلى عنوان URL http://istia.univ-angers.fr. |
في هذا المثال البسيط، يمكننا أن نرى أنه لإنشاء المستند بأكمله، يجب على المتصفح إرسال طلبين إلى الخادم:
http://localhost/exemple1.htm لاسترداد مصدر HTML للمستند
http://localhost/univ01.gif لاسترداد الصورة univ01.gif
5.2.2. إنشاء نموذج
الغرض من نموذج HTML هو تزويد المستخدم بصفحة لإدخال المعلومات تشبه نماذج الإدخال الموجودة في Windows. يتم إرسال نموذج الإدخال إلى المتصفح كوثيقة HTML. يعرض المتصفح النموذج للمستخدم، الذي يقوم بملئه وإرساله باستخدام زر بهذه الوظيفة. ثم يقوم المتصفح بنقل القيم التي تم إدخالها إلى الخادم للمعالجة. سنرى أنه لا يرسل النموذج بأكمله إلى الخادم، بل يرسل القيم التي تم إدخالها فقط. يوضح المثال التالي نموذج ويب تم إنشاؤه أيضًا باستخدام WebMatrix:

فيما يلي كود 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 |
<form name="form" method="post"> | |
<input type="text" maxlength="30" value="بضع كلمات" name="txtInput" /> | |
<input type="password" maxlength="12" size="12" value="aPassword" name="txtMdp" /> | |
<textarea name="inputArea">السطر 1 السطر 2</textarea> | |
<input type="radio" value="yes" name="rdMarie" />نعم <input type="radio" checked value="no" name="rdMarie" />لا | |
<input type="checkbox" value="one" name="C1" />1 <input type="checkbox" checked value="two" name="C2" />2 <input type="checkbox" value="three" name="C3" />3 | |
<select name="cmbValeurs"> <option value="1">option1</option> <option value="2" selected>الخيار 2</option> <option value="3">الخيار 3</option> </select> | |
<select size="3" name="lstSimple"> <option value="1" selected>القائمة 1</option> <خيار القيمة="2">القائمة 2</option> <option value="3">القائمة 3</option> <option value="4">القائمة 4</option> <option value="5">القائمة 5</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="aValue" /> | |
<input type="submit" value="إرسال" name="submitButton" /> | |
<input type="reset" value="Reset" name="btnReset" runat="server" /> | |
<input onclick="clear()" type="button" value="مسح" name="btnClear" /> |
دعونا نستعرض عناصر التحكم المختلفة هذه.
5.2.2.1. زر
<form name="form" method="post"> |
<form name="..." method="..." action="...">...</form> | |
name="formexample": اسم النموذج method="..." : الطريقة التي يستخدمها المتصفح لإرسال القيم التي تم جمعها في النموذج إلى خادم الويب action="..." : عنوان URL الذي سيتم إرسال القيم التي تم جمعها في النموذج إليه. يُحاط نموذج الويب بعلامتي <form>...</form>. ويمكن أن يكون للنموذج اسم (name="xx"). وينطبق هذا على جميع عناصر التحكم الموجودة داخل النموذج. ويكون هذا الاسم مفيدًا إذا كان مستند الويب يحتوي على نصوص برمجية تحتاج إلى الإشارة إلى عناصر النموذج. الغرض من النموذج هو جمع المعلومات التي يدخلها المستخدم عبر لوحة المفاتيح أو الماوس وإرسالها إلى عنوان URL لخادم الويب. أي عنوان؟ العنوان المشار إليه في السمة action="URL". إذا كانت هذه السمة مفقودة، فسيتم إرسال المعلومات إلى عنوان URL للمستند الذي يوجد فيه النموذج. كيف يرسل عميل الويب المعلومات (البيانات الموجودة في النموذج) إلى خادم الويب؟ لقد تناولنا هذا بالتفصيل. يمكنه استخدام طريقتين مختلفتين تسميان POST و GET. تحدد السمة method="method" لعلامة <form>، حيث يتم تعيين method إلى GET أو POST، للمتصفح الطريقة التي يجب استخدامها لإرسال المعلومات التي تم جمعها في النموذج إلى عنوان URL المحدد بواسطة السمة action="URL". عندما لا يتم تحديد السمة method، يتم استخدام طريقة GET بشكل افتراضي. |
5.2.2.2. حقل الإدخال

<input type="text" maxlength="30" value="some words" name="txtInput" /> <input type="password" maxlength="12" size="12" value="aPassword" name="txtMdp" /> |
<input type="..." name="..." size=".." value=".."> توجد علامة الإدخال لمختلف عناصر التحكم. وهي سمة النوع التي تميز عناصر التحكم المختلفة هذه عن بعضها البعض. | |
type="text": تحدد أن هذا حقل إدخال نصي type="password": يتم استبدال الأحرف الموجودة في حقل الإدخال بعلامات نجمية (*). هذا هو الاختلاف الوحيد عن حقل الإدخال العادي. هذا النوع من عناصر التحكم مناسب لإدخال كلمات المرور. size="12": عدد الأحرف المرئية في الحقل — لا يمنع إدخال المزيد من الأحرف maxlength="30": يحدد الحد الأقصى لعدد الأحرف بـ 30 — يتولى المتصفح مسؤولية تطبيق هذه السمة name="txtInput": اسم عنصر التحكم value="بعض الكلمات": النص الذي سيتم عرضه في حقل الإدخال. |
5.2.2.3. حقل إدخال متعدد الأسطر

<textarea name="inputArea">السطر 1 السطر 2</textarea> |
<textarea ...>text</textarea> يعرض حقل إدخال متعدد الأسطر مع نص أولي بداخله | |
rows="2": عدد الأسطر cols="'20": عدد الأعمدة name="areaSaisie": اسم عنصر التحكم |
5.2.2.4. أزرار الاختيار
![]()
<input type="radio" value="yes" name="rdMarie" />نعم <input type="radio" checked value="no" name="rdMarie" />لا |
<input type="radio" attribute2="value2" ..../>text يعرض زر اختيار مع نص بجانبه. | |
name="rdMarie": اسم عنصر التحكم. تشكل أزرار الاختيار التي تحمل الاسم نفسه مجموعة من الأزرار المتنافية: لا يمكن تحديد سوى زر واحد منها. value="value": القيمة المخصصة لزر الاختيار. لا تخلط بين هذه القيمة والنص المعروض بجانب زر الاختيار. النص مخصص للعرض فقط. checked: إذا كانت هذه الكلمة الرئيسية موجودة، يتم تحديد زر الاختيار؛ وإلا، لا يتم تحديده. |
5.2.2.5. مربعات الاختيار
<input type="checkbox" value="one" name="C1" />1 <input type="checkbox" checked value="two" name="C2" />2 <input type="checkbox" value="three" name="C3" />3 |
![]()
<input type="checkbox" attribute2="value2" ..../>text تعرض مربع اختيار مع نص بجانبه. | |
name="C1": اسم عنصر التحكم. قد تحمل مربعات الاختيار نفس الاسم أو لا. تشكل مربعات الاختيار التي تحمل نفس الاسم مجموعة من مربعات الاختيار المرتبطة. value="value": القيمة المعينة لمربع الاختيار. لا تخلط بين هذه القيمة والنص المعروض بجانب زر الاختيار. النص مخصص للعرض فقط. checked: إذا كانت هذه الكلمة الرئيسية موجودة، يتم تحديد زر الاختيار؛ وإلا، لا يتم تحديده. |
5.2.2.6. قائمة منسدلة (مجموعة)
<select name="cmbValues"> <option value="1">choice1</option> <option value="2" selected>الخيار 2</option> <option value="3">الخيار 3</option> </select> |
![]()
<select size=".." name=".."> <option [selected="selected"] [value="value"]>نص</option> ... </select> تعرض النص الموجود بين علامتي <option>...</option> في قائمة | |
name="cmbValues": اسم عنصر التحكم. size="1": عدد عناصر القائمة المرئية. تجعل السمة size="1" القائمة مكافئة لمربع القائمة المنسدلة. هذه هي القيمة الافتراضية في حالة عدم وجود السمة [size]. selected="selected": إذا كانت هذه السمة موجودة لعنصر في القائمة، يظهر هذا العنصر محددًا في القائمة. في المثال أعلاه، يظهر عنصر القائمة "choice2" كعنصر محدد في مربع القائمة المنسدلة عند عرضه لأول مرة. value="value": يحدد القيمة التي سيتم إرسالها إلى الخادم إذا تم تحديد العنصر. إذا كانت هذه السمة مفقودة، يتم إرسال النص المرتبط بالخيار إلى الخادم. |
5.2.2.7. قائمة الاختيار الفردي
<select size="3" name="lstSimple"> <option value="1" selected>list1</option> <option value="2">list2</option> <option value="3">القائمة 3</option> <option value="4">القائمة 4</option> <option value="5">القائمة 5</option> </select> |

<select size=".." name=".."> <option [selected] [value="value"]>...</option> ... </select> تعرض النص الموجود بين علامتي <option>...</option> في قائمة | |
هي نفسها المستخدمة في القائمة المنسدلة التي تعرض عنصرًا واحدًا فقط. يختلف هذا العنصر عن القائمة المنسدلة السابقة فقط في سمة size>1. |
5.2.2.8. قائمة التحديد المتعدد
<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="value"]>...</option> ... </select> تعرض النص الموجود بين علامتي <option>...</option> في قائمة | |
multiple: يسمح بتحديد عناصر متعددة في القائمة. في المثال أعلاه، تم تحديد العنصرين list1 و list3. |
5.2.2.9. زر
<input onclick="clear()" type="button" value="Clear" name="btnClear" /> |
![]()
<input type="button" value="..." name="..." onclick="clear()" ....> | |
type="button": تحدد عنصر تحكم زر. هناك نوعان آخران من الأزرار: submit و reset. value="Clear": النص المعروض على الزر onclick="function()": يسمح لك بتعريف دالة يتم تنفيذها عندما ينقر المستخدم على الزر. هذه الدالة هي جزء من البرامج النصية المحددة في مستند الويب المعروض. الصيغة أعلاه هي صيغة JavaScript. إذا كانت البرامج النصية مكتوبة بلغة VBScript، فستكتب onclick="function" بدون الأقواس. تظل الصيغة كما هي إذا كان من الضروري تمرير معلمات إلى الدالة: onclick="function(val1, val2,...)" في مثالنا، يؤدي النقر على زر "Clear" إلى استدعاء دالة JavaScript التالية: تعرض وظيفة clear رسالة: ![]() |
5.2.2.10. زر الإرسال
<input type="submit" value="إرسال" name="btnSubmit" /> |
![]()
<input type="submit" value="إرسال" name="btnSend"> | |
type="submit": تحدد الزر كزر لإرسال بيانات النموذج إلى خادم الويب. عندما ينقر المستخدم على هذا الزر، سيرسل المتصفح بيانات النموذج إلى عنوان URL المحدد في سمة action لعلامة <form>، باستخدام الطريقة المحددة بواسطة سمة method لنفس العلامة. value="Submit": النص المعروض على الزر |
5.2.2.11. زر إعادة الضبط
<input type="reset" value="Reset" name="btnReset" runat="server" /> |
![]()
<input type="reset" value="إعادة تعيين" name="btnReset"> | |
type="reset": يحدد الزر كزر إعادة تعيين النموذج. عندما ينقر المستخدم على هذا الزر، سيقوم المتصفح باستعادة النموذج إلى الحالة التي تم استلامه بها. value="Reset": النص المعروض على الزر |
5.2.2.12. الحقل المخفي
<input type="hidden" name="secret" value="aValue" /> |
<input type="hidden" name="..." value="..."> | |
type="hidden": تحدد أن هذا حقل مخفي. الحقل المخفي هو جزء من النموذج ولكنه لا يظهر للمستخدم. ومع ذلك، إذا طلب المستخدم من متصفحه عرض شفرة المصدر، فسيرى وجود علامة <input type="hidden" value="..."> وبالتالي قيمة الحقل المخفي. value="aValue": قيمة الحقل المخفي. ما الغرض من الحقل المخفي؟ إنه يسمح لخادم الويب بالاحتفاظ بالمعلومات عبر طلبات العميل. لنفترض وجود تطبيق تسوق عبر الويب. يشتري العميل عنصرًا أوليًا art1 بكمية q1 في الصفحة الأولى من الكتالوج ثم ينتقل إلى صفحة جديدة في الكتالوج. لتذكر أن العميل اشترى q1 من العناصر art1، يمكن للخادم وضع هاتين المعلومتين في حقل مخفي في نموذج الويب للصفحة الجديدة. في هذه الصفحة الجديدة، يشتري العميل q2 وحدة من العنصر art2. عندما يتم إرسال البيانات من هذا النموذج الثاني إلى الخادم، لن يتلقى الخادم المعلومات (q2,art2) فحسب، بل سيتلقى أيضًا (q1,art1)، والتي تعد أيضًا جزءًا من النموذج كحقل مخفي لا يمكن للمستخدم تعديله. ثم يقوم خادم الويب بوضع المعلومات (q1،art1) و(q2،art2) في حقل مخفي جديد وإرسال صفحة كتالوج جديدة. وهكذا دواليك. |
5.3. إرسال قيم النموذج إلى خادم الويب عبر متصفح
نعلم بالفعل، من الفصل السابق، كيف ينقل العميل المعلومات إلى الخادم. ويقوم بذلك إما عن طريق:
- طلب HTTP GET: url?param1=va1¶m2=val2&....
- طلب HTTP POST متبوعًا بوثيقة تحتوي على سلسلة المعلمات param1=va1¶m2=val2&....
سيستخدم المتصفح إحدى هاتين الطريقتين اعتمادًا على ما إذا كانت السمة [method] لعلامة [form] مضبوطة على GET أو POST. وهذا ما سنقوم بتوضيحه الآن. الصفحة التي نظرنا إليها سابقًا هي صفحة ثابتة. للوصول إلى رؤوس HTTP المرسلة من المتصفح الذي يطلب هذا المستند، سنقوم بتحويلها إلى صفحة ديناميكية لخادم ويب .NET (IIS أو Cassini). يتم وضع الكود الثابت السابق في ملف باسم [form_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>
ترتبط صفحة العرض أعلاه بوحدة التحكم [form_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
' saves the current query in request.txt of the page folder
Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
Me.Request.SaveAs(requestFileName, True)
End Sub
End Class
في كل مرة يتم فيها استدعاء المستند [form_get.aspx]، سيتم حفظ طلب العميل في ملف [request.txt] بواسطة الإجراء Page_Init. لقد سبق أن تعرفنا على طريقة التشغيل هذه، لذا لن نعلق أكثر على وحدة التحكم.
5.3.1. طريقة GET
دعونا نجري اختبارًا أوليًا، حيث يتم تعريف علامة FORM في كود HTML للمستند على النحو التالي:
<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:

لقد أرسل المتصفح طلبًا للتو، ونعلم أنه تم تسجيله في ملف [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 من قبل المستخدم. نملأ النموذج على النحو التالي:

نستخدم زر [إرسال] الموجود أعلاه. وفيما يلي كود HTML الخاص به:
عند النقر على زر [إرسال]، يرسل المتصفح معلمات النموذج (العلامة <form>) إلى عنوان URL المحدد في سمة [action] للعلامة <form action="URL">، إن وجدت. إذا لم تكن هذه السمة موجودة، يتم إرسال معلمات النموذج إلى عنوان URL الذي قدم النموذج. وهذا هو الحال هنا. لذلك، يجب أن يؤدي زر [إرسال] إلى إرسال طلب من المتصفح إلى عنوان URL [http://localhost/form2/formulaire_get.aspx] مع تضمين معلمات النموذج. نظرًا لأن الصفحة [formulaire_get.aspx] تخزن الطلب المستلم، يجب أن نتمكن من رؤية كيفية إرسال العميل لهذه المعلمات. دعونا نجرب ذلك. نضغط على زر [إرسال]. نتلقى الاستجابة التالية من المتصفح:

هذه هي الصفحة الأولية، ولكن يمكنك ملاحظة أن عنوان URL قد تغير في حقل [Address] بالمتصفح. فقد أصبح كما يلي:
http://localhost/form2/formulaire_get.aspx?rdMarie=oui&C1=un&C2=deux&txtSaisie=programmation+asp.net&txtMdp=unMotDePasse&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Envoyer&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 مشابه جدًا للطلب الذي أرسله المتصفح في البداية عندما طلب المستند دون تمرير أي معلمات. هناك اختلافان:
تمت إضافة معلمات النموذج إلى عنوان URL للمستند بالشكل التالي: ?param1=val1¶m2=val2&... | |
يستخدم العميل رأس HTTP هذا للإشارة إلى عنوان URL للمستند الذي كان يعرضه عند إجراء الطلب |
دعونا نلقي نظرة فاحصة على كيفية تمرير المعلمات في طلب GET URL?param1=value1¶m2=value2&... HTTP/1.1، حيث المعلمات هي أسماء عناصر التحكم في نموذج الويب والقيم هي القيم المرتبطة بها. فيما يلي جدول من ثلاثة أعمدة:
- العمود 1: يعرض تعريف عنصر تحكم HTML من المثال
- العمود 2: يوضح كيف يظهر عنصر التحكم هذا في المتصفح
- العمود 3: يعرض القيمة التي أرسلها المتصفح إلى الخادم لعنصر التحكم في العمود 1 بالشكل الذي يتخذه في طلب GET من المثال
عنصر تحكم HTML | عرض ما قبل التحقق من الصحة | القيمة (القيم) المُرجعة |
<input type="radio" value="yes" name="rdMarie" />نعم <input type="radio" checked value="no" name="rdMarie" />لا | - قيمة سمة value الخاصة بالزر التي اختارها المستخدم. | |
<input type="checkbox" value="one" name="C1" />1 <input type="checkbox" checked value="two" name="C2" />2 <input type="checkbox" value="three" name="C3" />3 | C1=واحد C2=اثنان - قيم سمات القيمة لمربعات الاختيار التي حددها المستخدم | |
<input type="text" maxlength="30" value="بعض كلمات" name="txtInput" /> | txtSaisie=البرمجة+asp.net - النص الذي يكتبه المستخدم في . تم استبدال المسافات بعلامة + | |
<input type="password" maxlength="12" size="12" value="aPassword" name="txtMdp" /> | txtMdp="thisIsSecret" - النص الذي كتبه المستخدم في . النص الذي تمت كتابته فعليًا هو "thisIsSecret". فقد فقدان الحرف الأخير بسبب حدد maxlength="12" عدد الأحرف إلى 12. | |
<textarea name="areaSaisie"> السطر 1 السطر 2</textarea> | ![]() | areaSaisie=أساسيات+ البرمجة%0D%0A البرمجة+الويب - نص مكتوب من قبل المستخدم في . %OD%OA هو . تم استبدال المسافات بعلامة + |
<select name="cmbValeurs"> <option value="1">الخيار 1 </option> <option value="2" selected>الخيار 2 </option> <خيار القيمة="3">الخيار 3 </option> </select> | cmbValues=3 - القيمة التي اختارها المستخدم من قائمة الاختيار الفردي | |
<select size="3" name="lstSimple"> <option value="1" selected>list1</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> <خيار القيمة="3" محدد>متعدد3 </option> <option value="4">multiple4 </option> <option value="5">multiple5 </option> </select> | ![]() | lstMultiple=2 lstMultiple=4 - القيم التي اختارها المستخدم في قائمة التحديد المتعدد |
<input type="submit" value="إرسال" name="btnSubmit" /> | btnEnvoyer=إرسال - سمة الاسم والقيمة للزر المستخدم لإرسال بيانات النموذج إلى الخادم | |
<input type="hidden" name="secret" value="aValue" /> | secret=aValue - سمة 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]، أي إلى المستند الذي أنشأناه في البداية. لم نكتب أي كود لاسترداد ومعالجة المعلمات التي يرسلها لنا العميل. لذا، يحدث كل شيء كما لو كان طلب العميل ببساطة:
ولهذا السبب، استجابةً لزر [Submit] الخاص بنا، تلقينا نفس الصفحة التي تم الحصول عليها في البداية عن طريق طلب عنوان URL [http://localhost/form2/formulaire_get.aspx] بدون معلمات.
5.3.2. طريقة POST
تم الآن تكوين مستند HTML بحيث يستخدم المتصفح طريقة POST لإرسال قيم النموذج إلى خادم الويب. للقيام بذلك، ننسخ ملف [form_get.aspx] إلى [form_post.aspx] ونقوم بتعديل علامة <form> فقط في [form_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">
لا حاجة لتغيير وحدة التحكم [form_get.aspx.vb]، لذا نتركها كما هي. نطلب المستند الجديد عبر عنوان URL [http://localhost/form2/formulaire_post.aspx]، ونملأ النموذج كما فعلنا مع طريقة GET، ونرسل المعلمات إلى الخادم باستخدام الزر [Submit]. نتلقى صفحة الاستجابة التالية من الخادم:

وبالتالي نحصل على نفس النتيجة كما في طريقة GET، أي الصفحة الأولية. لاحظ اختلافًا واحدًا: في حقل [Address] بالمتصفح، لا تظهر المعلمات المرسلة. الآن، لنلقِ نظرة على الطلب الذي أرسله العميل وتم حفظه في الملف [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 الخاص بالعميل:
تم استبدال طلب GET بطلب POST. لم تعد المعلمات موجودة في السطر الأول من الطلب. يمكننا أن نرى أنها موضوعة الآن بعد طلب HTTP بعد سطر فارغ. ترميزها مطابق للترميز الموجود في طلب GET. | |
عدد الأحرف "المنشورة"، أي عدد الأحرف التي يجب على خادم الويب قراءتها بعد استلام رؤوس HTTP لاسترداد المستند المرسل من قبل العميل. المستند المقصود هنا هو قائمة قيم النموذج. | |
يحدد نوع المستند الذي سيرسله العميل بعد رؤوس HTTP. يشير النوع [application/x-www-form-urlencoded] إلى أنه مستند يحتوي على قيم النموذج. |
هناك طريقتان لنقل البيانات إلى خادم الويب: GET و POST. هل إحدى الطريقتين أفضل من الأخرى؟ لقد رأينا أنه إذا تم إرسال قيم النموذج بواسطة المتصفح باستخدام طريقة GET، فسيعرض المتصفح عنوان URL المطلوب في حقل العنوان الخاص به في النموذج URL?param1=val1¶m2=val2&.... يمكن اعتبار ذلك ميزة أو عيبًا:
- ميزة إذا كنت تريد السماح للمستخدم بحفظ عنوان URL المعلم هذا في إشاراته المرجعية
- عيب إذا كنت لا تريد أن يتمكن المستخدم من الوصول إلى معلومات معينة في النموذج، مثل الحقول المخفية
من الآن فصاعدًا، سنستخدم طريقة POST بشكل حصري تقريبًا في نماذجنا.
5.4. معالجة قيم النماذج من جانب الخادم
5.4.1. نظرة عامة على المثال
الآن بعد أن حددنا العلاقة بين علامة HTML <form method="GET/POST" ...> والطريقة التي يرسل بها المتصفح قيم النماذج، أصبحنا نعرف كيفية استردادها من جانب الخادم. قدم الفصل السابق الإجابة:
- إذا كانت طريقة علامة <form> هي GET، فسيتم استرداد قيم المعلمات من مجموعة [Request.QueryString]
- إذا كانت طريقة علامة <form> هي POST، فسيتم استرداد قيم المعلمات "المرسلة" من مجموعة [Request.Form]. وهنا يلزم توضيح. يمكن لعلامة <form> تحديد عنوان URL الهدف لطلب GET أو POST باستخدام السمة [action]. يمكن تكوين عنوان URL هذا بغض النظر عما إذا كان طلب GET أو POST، في النموذج action="url?param1=val1¶m2=val2&..". ثم تُضاف هذه المعلمات إلى تلك الموجودة بين علامتي <form> و </form>، والتي سيتم إرسالها إلى الخادم عبر طلب GET أو POST. ونظرًا لأنها جزء من عنوان URL الهدف، فسيتم استردادها من مجموعة [Request.QueryString] بغض النظر عما إذا كان الطلب هو GET أو POST.
سنقوم الآن بكتابة تطبيق MVC مع عرضين:
- العرض الأول هو النموذج السابق. سنسميه [form_view].
- العرض الثاني هو صفحة معلومات تسرد القيم التي تم إدخالها في الصفحة الأولى. يتيح رابط للمستخدم العودة إلى النموذج. سنسمي هذا العرض [view_confirmation].
يتم إرسال [form_view] إلى المستخدم، الذي يقوم بملئه وإرساله. قد يبدو كما يلي قبل الإرسال مباشرة:

ينقر المستخدم على زر [Submit] لإرسال إدخالاته. وفي المقابل، يتلقى [validation_view] التالي:

5.4.2. وحدة التحكم في التطبيق
رأينا في الفصل السابق أنه يمكننا تعيين دور وحدة التحكم لتطبيق MVC إلى ملف [global.asax]، الذي تمر عبره جميع طلبات العميل. لقد قدمنا بالفعل تطبيق MVC تم إنشاؤه بهذه الطريقة، وسنتبع هنا نموذج التطوير الذي تم تقديمه آنذاك. سيكون ملف [global.asax] كما يلي:
يتكون من سطر واحد يشير إلى وحدة التحكم الموجودة في ملف [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)
' retrieve the action to be performed
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' execute the action
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
يعمل وحدة التحكم على النحو التالي:
- تبحث عن سلسلة معلمات تحتوي على المعلمة [action] في عنوان URL الهدف. إذا كانت هذه المعلمة مفقودة، فإنها تتصرف كما لو أن [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¶m2=val2&... وهذا ما يتم هنا، حيث نمرر المعلمة [action=validation] لإخبار وحدة التحكم بالإجراء الذي يجب أن تتخذه. لاحظ أن سلسلة المعلمات هذه لا يسبقها عنوان ويب. وبالتالي، سيرسل المتصفح معلمات النموذج إلى العنوان الذي قدم هذا النموذج. في المثال أعلاه، هذا العنوان هو [http://localhost/mvcform1]. وبالتالي، سيقوم المتصفح بإرسال طلب [POST /mvcform1?action=validation] إلى الجهاز [localhost].
تمت إضافة أزرار للسماح للمستخدم بإلغاء تحديد العناصر من قوائم [lstSimple] و [lstMultiple]:

وهذا يترجم إلى كود 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>
يؤدي النقر على زر [مسح] إلى إلغاء تحديد جميع العناصر الموجودة في القائمة المرتبطة به. لنأخذ قائمة [lstMultiple] كمثال. يؤدي النقر على زر [مسح] المقابل إلى تشغيل دالة JavaScript [raz(lstMultiple)]. تذكر أن كود JavaScript في مستند HTML المعروض بواسطة متصفح يتم تنفيذه بواسطة المتصفح نفسه، وليس بواسطة الخادم. JavaScript هي لغة شاملة للغاية تسمح لك بإضافة ميزات ديناميكية إلى الصفحات دون تدخل من الخادم. دالة [raz] هي كما يلي:
تأخذ هذه الدالة معلمةً هي كائن JavaScript يمثل قائمة HTML. يحتوي هذا الكائن على خصائص وأساليب. إحدى خصائصه هي [selectedIndex]، التي تمثل قيمتها رقم الخيار الأول المحدد في قائمة HTML. إذا لم يكن هناك أي خيار محدد، تكون قيمة هذه الخاصية -1. وبالعكس، يؤدي تعيين قيمة لهذه الخاصية إلى تحديد عنصر جديد في قائمة HTML، بينما يعني تعيينها إلى -1 عدم تحديد أي عنصر. وهذا ما يتم هنا.
أخيرًا، لاحظ أن كود العرض [form.aspx] لا يرافقه وحدة تحكم [form.aspx.vb]. في الواقع، لا يوجد محتوى ديناميكي تم إنشاؤه بواسطة الخادم في مستند HTML، لذا لا توجد حاجة لوحدة تحكم.
5.4.4. معالجة إجراء التحقق من الصحة
عندما يعالج وحدة التحكم إجراء "التحقق من الصحة"، يجب أن تنشئ صفحة تسرد القيم التي أدخلها المستخدم. وتقع مسؤولية تنفيذ هذه المهمة على عاتق الصفحة [validation.aspx]. من الناحية المرئية، تبدو الصفحة كما يلي:

وإليك كود 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
'retrieve posted parameters
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
' retrieves the value of field [field] from the posted request
' anything?
If Request.Form(champ) Is Nothing Then Return ""
' retrieve the value(s) of the
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=line1\r\nline2\r\n... حيث \r هو الرمز ASCII 13 (إرجاع الحامل) و\n هو الرمز ASCII 10 (تغذية السطر). وبالتالي، فإن الدالة getValue(areaSaisie) هي السلسلة "line1\r\nline2\r\n...". يتم تقسيم هذه السلسلة إلى أسطر باستخدام طريقة [Regex.Split]. وينتج عن ذلك مصفوفة من السلاسل {line1,line2,...}. يتم تحويل هذا المصفوف إلى السلسلة "line1,line2,..." باستخدام طريقة [String.Join]. وهذه السلسلة النهائية هي التي سيتم عرضها كقيمة لحقل [areaSaisie]. كان الهدف هنا هو توضيح كيفية استخراج الأسطر الفردية من حقل [TextArea] في HTML.
5.4.5. الاختبارات
نضع جميع الملفات (global.asax، global.asax.vb، formulaire.aspx، validation.aspx، validation.aspx.vb) في مجلد باسم <application-path>. نبدأ تشغيل خادم Cassini بالمعلمات (<application-path>,/mvcform1). نقوم بإنشاء ملف [default.aspx] فارغ في مجلد <application-path>، ثم نطلب عنوان URL [http://localhost/mvcform1]. نظرًا لأن [/mvcform1] هو المسار الافتراضي لمجلد وليس مستندًا، فسيعرض خادم الويب مستند [default.aspx] إذا كان موجودًا. ولهذا السبب قمنا بإنشائه. قبل عرضه، سيتم تشغيل البرنامج النصي [global.asax] وسيعرض في النهاية الصفحة [form.aspx]. لهذا السبب يمكن أن يكون ملف [default.aspx] فارغًا.
لنفترض أن النموذج الذي تم التحقق من صحته هو كما يلي:

يؤدي النقر فوق الزر [Submit] إلى إرجاع الصفحة التالية:

أولاً، لاحظ عنوان 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="yes" name="rdMarie">نعم <input type="radio" checked value="no" name="rdMarie">لا | القيمة التي تم الحصول عليها هي سمة [value] لمربع الاختيار |
C1 | a | <input type="checkbox" value="one" name="C1">1 | نفس |
C2 | اثنان | <input type="checkbox" محدد value="two" name="C2">2 | نفس |
C3 | <input type="checkbox" value="three" name="C3">3 | لم يقم المستخدم بتحديد هذا الزر. وبالتالي لم يتم إرسال قيمته بواسطة المتصفح. في الكود، كانت الحالة [Request.Form("C3") is Nothing] صحيحة بالتالي. | |
txtInput | البرمجة ASP.NET | <input type="text" ... name="txtSaisie"> | القيمة التي يتم إرجاعها هي النص الموجود في حقل الإدخال وقت التحقق من الصحة |
txtMdp | كلمة المرور | <input type="password" ...name="txtMdp"> | same |
حقل_الإدخال | أساسيات برمجة الويب | <textarea name="areaSaisie"> ...</textarea> | نفس |
cmbValues | 3 | <select name="cmbValues"> ... <option value="3">choice3</option> </select> | القيمة التي تم الحصول عليها هي سمة [value] للخيار المحدد |
lstSimple | 3 | <select size="3" name="lstSimple"> .... <option value="3">list3</option> ... </select> | نفس |
lstMultiple | 2 4 | <select multiple size="3" name="lstMultiple"> ... <option value="2">multiple2 </option> ... <option value="4">multiple4 </option> ... </select> | القيم التي تم الحصول عليها هي قيم سمات [value] للخيارات المحددة |
secret | aValue | <input type="hidden" name="secret" value="aValue"> | القيمة التي تم الحصول عليها هي سمة [value] للحقل المخفي |
الآن دعونا نلقي نظرة على القوائم. لنفترض أنه في وقت التحقق من الصحة، تكون حالة النموذج كما يلي:

- تم تحديد الخيار [choice1] في مربع القائمة المنسدلة
- لم يتم تحديد أي خيار في القائمتين الأخريين. استخدمنا أزرار [Clear] لتحقيق ذلك.
إليك الصفحة التي يتم إرجاعها بعد التحقق من الصحة:

عندما لا يتم تحديد أي قيمة في قائمة، لا يرسل المتصفح معلمة لها. في كود [validation.aspx.vb]، تكون التعبيرات [Request.Form("lstSimple")] و [Request.Form("lstMultiple")] مساوية للثابت [Nothing]، ومن ثم تظهر النتيجة الموضحة أعلاه.
5.5. الحفاظ على حالة الصفحة
5.5.1. الحفاظ على حالة الصفحة باستخدام جلسة عمل
نقوم بنسخ التطبيق السابق بالكامل إلى مجلد جديد. نضيف رابطًا إلى صفحة [validation.aspx] يسمح للمستخدم بالعودة إلى النموذج:

التغيير الذي سيتم إجراؤه على صفحة [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=form]، مما يسمح للخادم بمعرفة أنه يجب عليه عرض النموذج كما كان عند إرساله. وهذا يختلف عن الإجراء [init]، الذي يعرض نموذجًا محددًا مسبقًا. لا يحتوي عنوان URL الذي يحتوي على المعلمة [?action=form] على عنوان URL فعلي. وبالتالي، سيكون هو نفسه الذي عرض صفحة الإرسال. كما رأينا في المثال السابق، هذا هو عنوان URL لمجلد التطبيق. وبالتالي، سيمر الطلب عبر وحدة التحكم. يجب على وحدة التحكم الآن معالجة الإجراء [form]. يتم تعديل الكود في [global.asax.vb] على النحو التالي:
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
' retrieve the action to be performed
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' execute the action
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
إذا كان الإجراء هو "form"، فإننا ببساطة نحيل الطلب إلى صفحة [form.aspx]. ونحن نعلم أن هذه الصفحة تعرض نموذجًا محددًا مسبقًا بدون أجزاء متغيرة. وبالتالي، لا يمكن لهذه الصفحة عرض النموذج بالقيم التي كان يحتوي عليها عند إرساله. ونحن نحاول تسليط الضوء على هذه النقطة هنا. إذا تم وضع جميع ملفات التطبيق في <application-path>، فإننا نطلق Cassini بالمعلمات (<application-path>,/mvcform2) ثم نطلب عنوان URL [http://localhost/mvcform2]. نحصل على الصفحة التالية (عرض جزئي):

نملأ النموذج على النحو التالي ثم نرسله:

نحصل على صفحة التأكيد التالية:

نستخدم رابط [العودة إلى النموذج] الموجود (ولكن غير معروض) في الصفحة أعلاه. نتلقى الاستجابة التالية من الخادم:

نلاحظ ما يلي:
- أن عنوان URL المطلوب يحتوي بالفعل على المعلمة action=form كما هو مطلوب
- أن النموذج المعروض قد فقد القيم التي تم إدخالها.
نحن نعرف سبب عدم تمكننا من استرداد القيم التي تم إدخالها. إذا نظرنا إلى كود مستند [form.aspx]، نرى أن كل شيء ثابت، لذا فهو مجبر على عرض نفس الصفحة في كل مرة. من الواضح أننا بحاجة إلى جعل هذا الكود ديناميكيًا. يجب أن يعرض القيم التي تم التحقق من صحتها من قبل المستخدم. ولكن أين يجب أن نخزنها؟
دعونا نتذكر القانون الحديدي لبروتوكول HTTP عديم الحالة:
- يتم طلب عنوان URL [http://localhost/mvcform2] — ويتم تلقي استجابة. تم فتح اتصال TCP-IP بين العميل والخادم في بداية الطلب وإغلاقه في نهاية الاستجابة.
- يقوم المستخدم بإدخال البيانات ثم إرسالها. يتم طلب عنوان URL [http://localhost/mvcform2/?action=validation] — ويتم تلقي استجابة. تم فتح اتصال TCP/IP جديد ثم إغلاقه بين الطرفين.
- ينقر المستخدم على الرابط [العودة إلى النموذج]. يتم طلب عنوان URL [http://localhost/mvcform2/?action=formulaire] — ويتم تلقي استجابة. تم فتح اتصال TCP/IP جديد ثم إغلاقه بين الطرفين.
دورات الطلب والاستجابة مستقلة عن بعضها البعض لأن كل منها يستخدم اتصال TCP-IP جديد. عندما يستخدم تطبيق خادم-عميل اتصال TCP-IP واحد لسلسلة من التبادلات، يمكن للخادم تحديد هوية العميل عبر اتصاله. وبالتالي يمكنه تخزين المعلومات التي سيربطها باتصال معين وبالتالي تتبع التبادلات. عندما تحدث التبادلات عبر اتصالات مختلفة، لا يمكن للخادم تحديد هوية العميل من خلال الاتصال. يلزم وجود طريقة أخرى. لقد قدمنا إحدى هذه الطرق في الفصل السابق: آلية الجلسة. تسمح هذه الآلية لدورات الطلب والاستجابة بتخزين المعلومات في كائن [Session] يمكن الوصول إليه من قبل جميع الدورات اللاحقة.
الآن بعد أن أصبح لدينا تطبيق MVC مع جلسات، لم يعد بإمكاننا استخدام ملف [global.asax] كوحدة تحكم، كما هو موضح في الفصل السابق. يجب أن تتولى صفحة محددة مخصصة لهذا الغرض دور وحدة تحكم التطبيق. هنا، ستكون تلك الصفحة هي [main.aspx]. سنمضي على النحو التالي:
- عندما يرسل المستخدم بياناته (action=validation)، ستقوم وحدة التحكم [main.aspx.vb] بتخزينها في الجلسة الحالية قبل عرض صفحة التحقق من الصحة.
- عندما يلزم عرض النموذج مع القيم المدخلة (action=form)، ستقوم وحدة التحكم [main.aspx.vb] باستردادها من الجلسة ووضعها في السياق قبل عرض النموذج.
5.5.2. وحدة التحكم الجديدة للتطبيق
يتكون وحدة تحكم التطبيق من ملفين [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
' retrieve the action to be performed
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' execute the action
Select Case action
Case "init"
' the pre-filled form is displayed
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
Case "validation"
' the confirmation page is displayed after saving the values posted in the session
Session.Item("formulaire") = Request.Form
Server.Transfer("validation.aspx", True)
Case "formulaire"
' displays the form with values taken from the session
Context.Items("formulaire") = Session.Item("formulaire")
Server.Transfer("formulaire.aspx", True)
Case Else
' the pre-filled form is displayed
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
End Select
End Sub
Private Function initForm() As NameValueCollection
' initialize the form
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] في الجلسة المرتبطة بمفتاح "form". ثم يتم نقل التنفيذ إلى صفحة [validation.aspx]، التي ستعرض هذه القيم.
- بالنسبة للإجراءات الأخرى، يتم نقل التنفيذ في جميع الحالات إلى صفحة [formulaire.aspx]. تتوقع هذه الصفحة مفتاح "formulaire" في سياقها، والذي سيتم ربطه بكائن من النوع [Request.Form]، أي من النوع [NameValueCollection]. يجب أن يحتوي هذا الكائن على مجموعة القيم لحقول النموذج.
- إذا كان الإجراء هو [init] أو إجراء غير معروف، يتم إنشاء مجموعة القيم بشكل تعسفي بواسطة الدالة [initForm].
- إذا كان الإجراء هو [form]، فإن هذه المجموعة هي مجموعة [Request.Form] التي تم وضعها في الجلسة بواسطة إجراء [validation]
5.5.3. النموذج الجديد
نظرًا لأن التطبيق لم يعد يعرض نفس المحتوى في النموذج، يجب إنشاؤه ديناميكيًا. تصبح الصفحة [form.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:
المتغير | الدور |
سيكون له القيمة "checked" إذا تم تحديد زر الاختيار [yes]، وإلا فإن القيمة ستكون "" | |
نفس الشيء بالنسبة لزر الاختيار [no] | |
نفس الشيء بالنسبة لمربع الاختيار [C1] | |
نفس الشيء بالنسبة لمربع الاختيار [C2] | |
نفس الشيء بالنسبة لمربع الاختيار [C3] | |
النص المراد وضعه في حقل [txtInput] | |
النص المراد وضعه في حقل [txtPassword] | |
النص المراد وضعه في حقل [areaInput] | |
نص HTML للخيارات في القائمة المنسدلة [cmbValeurs] | |
نص HTML للخيارات في القائمة المنسدلة [lstSimple] | |
نص HTML للخيارات في القائمة المنسدلة [lstMultiple] | |
يتم حساب قيم هذه المتغيرات بواسطة وحدة التحكم في الصفحة [formulaire.aspx.vb]:
Imports Microsoft.VisualBasic
Imports System.Collections.Specialized
Public Class formulaire
Inherits System.Web.UI.Page
' constant form fields
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"}
' dynamic form fields
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
' retrieve the previous request from the session
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
' prepare the page to be displayed
' radio buttons
rdouichecked = ""
rdnonchecked = "checked"
If isEqual(form("rdMarie"), "oui") Then
rdouichecked = "checked"
rdnonchecked = ""
End If
' checkboxes
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"
' input fields
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
' lists
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
' renders HTML code for <select> tag options
' values: table of tag option values
' labels: table of tag option labels
' selections: options to select
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' browse the list of option values
For iValeur = 0 To valeurs.Length - 1
' check whether the current value should be selected
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' we integrate the HTML code from the
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' we return the result
Return toString
End Function
Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
' returns true if field is equal to value
If champ Is Nothing OrElse champ.ToString <> valeur Then
Return false
Else
Return true
End If
end function
End Class
عندما تبدأ صفحة [form.aspx] في التشغيل، ستجد في سياقها مفتاح "form" مرتبط بمجموعة قيم الحقول التي تحتاج إلى عرضها.
' retrieve the previous request from the session
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
قد يتساءل المرء عن سبب التحقق من وجود [Context.Items("form")]. في الواقع، يقوم وحدة التحكم بتعيين قيمة لهذا الكائن في جميع الحالات. ومع ذلك، لا شيء يمنع العميل من طلب صفحة [form.aspx] مباشرةً دون المرور عبر وحدة التحكم. إذا كان الأمر كذلك، فسيعمل الكود السابق مع مجموعة فارغة من القيم، ولكن لن يكون هناك "تعطل".
يقوم الكود بالتكرار عبر مجموعة القيم التي تلقاها لحساب جميع المتغيرات الديناميكية للصفحة HTML المرتبطة. على الرغم من أن هذا الكود طويل، إلا أنه ليس معقدًا بشكل خاص، وسنترك للقارئ استكشافه حتى لا نثقل هذا الشرح. ومع ذلك، سنركز على كيفية إنشاء كود HTML للقوائم الثلاث [select]. يتم إنشاء هذا الكود بواسطة الدالة التالية:
Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
' renders HTML code for <select> tag options
' values: table of tag option values
' labels: table of tag option labels
' selections: options to select
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' browse the list of option values
For iValeur = 0 To valeurs.Length - 1
' check whether the current value should be selected
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' we integrate the HTML code of the
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' we return the result
Return toString
End Function
لاحظ أن خيارات علامة <select> تتوافق مع كود HTML التالي:
وبالتالي، هناك ثلاث معلومات يجب إنشاؤها لكل خيار:
- قيمة الخيار في السمة [value]
- نص الخيار بين علامتي <option> و </option>
- الكلمة الرئيسية [selected] إذا كان يجب تحديد الخيار في القائمة
لإنشاء هذه المعلومات الثلاث لكل خيار، تتلقى الدالة [getOptions] ثلاث قيم:
- مصفوفة قيم الخيارات في [values]
- مصفوفة نصوص الخيارات في [labels]
- مصفوفة القيم المطلوب تحديدها في [selections]
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
'retrieve posted parameters
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")
' save them in the session
'Session("formulaire") = Request.Form
End Sub
Private Function getValue(ByVal champ As String) As String
' retrieves the value of field [field] from the posted request
' anything?
If Request.Form(champ) Is Nothing Then Return ""
' retrieve the value(s) of the
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، form.aspx، form.aspx.vb، validation.aspx، validation.aspx.vb] في <application-path> ويتم تشغيل Casini باستخدام المعلمات (<application-path>،/mvcform3). ثم نطلب عنوان URL [http://localhost/mvcform3/main.aspx]. نحصل على النموذج المُهيأ مسبقًا:

نملأ النموذج على النحو التالي:

نضغط على زر [Submit] أعلاه. نتلقى الرد التالي من الخادم:

نستخدم الرابط [Back to form] أعلاه للعودة إلى النموذج. نتلقى الرد الجديد التالي:

نرى النموذج تمامًا كما أرسلناه.
5.5.6. الخلاصة
أظهر لنا المثال السابق أنه من الممكن الحفاظ على حالة الصفحة طوال دورات الطلب والاستجابة بين العميل والخادم. ومع ذلك، فهذه ليست مهمة سهلة. وسنرى في فصل لاحق أنه من الممكن، باستخدام ASP.NET، السماح للخادم باستعادة حالة الصفحة تلقائيًا.



