Skip to content

5. التطبيق kation [SimuPaie] – الإصدار 2 – AJAX / ASP.NET

5.1. Introduction

تجمع تقنية AJAX (Asynchronous Javascript And Xml) بين مجموعة من التقنيات:

  • جافا سكريبت: يمكن أن تحتوي صفحة HTML المعروضة في متصفح على كود جافا سكريبت. يتم تنفيذ هذا الكود بواسطة المتصفح إذا لم يقم المستخدم بتعطيل تنفيذ كود جافا سكريبت على متصفحه. ظهرت هذه التقنية منذ بدايات الويب وتلقى اهتمامًا متجددًا منذ عام 2005 بفضل AJAX.
  • DOM: نموذج كائن المستند (Document Object Model). يمكن لرمز جافا سكريبت المضمن في صفحة HTML الوصول إلى المستند في شكل شجرة كائنات، وهي DOM. يتم تمثيل كل عنصر في المستند (حقل إدخال، علامة <div> مسماة، علامة <select>،...) بعقدة في الشجرة. يمكن لرمز جافا سكريبت تغيير المستند المعروض عن طريق تعديل DOM. على سبيل المثال، يمكنه تغيير النص المعروض في حقل إدخال عبر عقدة DOM التي تمثل هذا الحقل.

يستخدم AJAX جافا سكريبت لإجراء تبادلات بين المتصفح والخادم في الخلفية. للاستجابة لحدث مثل النقر على زر، سيتم تنفيذ كود جافا سكريبت بواسطة المتصفح لإرسال طلب HTTP إلى الخادم. سيحتوي هذا الطلب على معلمات تحدد للخادم ما يجب عليه فعله. وسيقوم الخادم بتنفيذ الإجراء المطلوب. سيرسل الخادم ردًا على المتصفح، دفق HTTP يحتوي على بيانات تسمح بتحديث جزئي للصفحة المعروضة حاليًا. سيتم تنفيذ ذلك عبر DOM الخاص بالوثيقة وتنفيذ كود جافا سكريبت المضمن في الوثيقة. يمكن أن تكون البيانات التي يرسلها الخادم بتنسيقات مختلفة: XML، HTML، JSON، نص غير منسق، ...

تكمن أهمية هذه التقنية في التحديث الجزئي للوثيقة المعروضة. وهذا يعني:

  • تقليل كمية البيانات المتبادلة بين العميل والخادم وبالتالي استجابة أسرع
  • واجهة رسومية أكثر سلاسة في الاستخدام لأن إجراءات المستخدم لا تؤدي إلى إعادة تحميل الصفحة بالكامل.

في شبكة إنترانت حيث تكون عمليات التبادل عبر الشبكة سريعة، تتيح AJAX إنشاء تطبيقات ويب ذات سلوك يشبه سلوك واجهات ويندوز التقليدية. يمكن بالفعل إدارة أحداث مثل تغيير التحديد في قائمة وتحديث الصفحة فوراً وجزئياً لتعكس هذا التغيير في التحديد. إن عدم إعادة تحميل الصفحة بالكامل يمنح المستخدم انطباعًا بالسلاسة التي يتمتع بها مع تطبيقات Windows. بالنسبة لتطبيقات الإنترنت، حيث قد تكون أوقات الاستجابة طويلة، تظل تقنية AJAX قابلة للاستخدام، لكن انطباع السلاسة يعتمد على أداء الشبكة.

تكمن الصعوبة الرئيسية في AJAX في لغة جافا سكريبت. تم إنشاؤها منذ بدايات الويب،

  • إلا أنه يثبت أنه غير عملي للبرمجة الموجهة للكائنات. فهو، على سبيل المثال، ليس لغة محددة النوع. لا يتم فيها تحديد نوع البيانات التي يتم التعامل معها. ونقترب هنا من لغات مثل Perl أو PHP.
  • ليس لها معيار مقبول من قبل جميع المتصفحات. لكل منها امتدادات "جافا سكريبت" خاصة بها، مما يجعل كود جافا سكريبت المكتوب لـ IE قد لا يعمل في Mozilla Firefox والعكس صحيح.
  • يصعب تصحيح أخطائه، حيث لا توفر المتصفحات أدوات فعالة لتصحيح أخطاء كود جافا سكريبت الذي تقوم بتنفيذه.

كل هذه المشاكل التي عانى منها جافا سكريبت جعلت استخدامه محدودًا قبل ظهور AJAX. وبمجرد إدراك فائدة تشغيل كود جافا سكريبت في الخلفية، لإرسال طلبات HTTP إلى خادم الويب واستخدام الرد الوارد منه للقيام، بفضل DOM، تحديثًا جزئيًا للوثيقة المعروضة، بدأت فرق التطوير العمل واقترحت أطر عمل تسمح بتنفيذ AJAX دون أن يضطر المطور إلى كتابة كود جافا سكريبت. ولهذا الغرض، تمت كتابة مكتبات جافا سكريبت قادرة على التكيف مع متصفح العميل. يتم إدراج كود جافا سكريبت في الصفحة المرسلة إلى المتصفح من جانب الخادم، وفقًا لتقنيات تختلف باختلاف إطار العمل المستخدم. توجد أطر عمل Ajax لكل من Java و.NET وPHP وRuby، ... AJAX مدمج في Visual Web Developer 2008.

5.2. مشروع Visual Web Developer للطبقة [web-ui-ajax]

يتم الحصول على الإصدار الجديد عن طريق نسخ الإصدار السابق. سيتم تعديل الصفحة [Default.aspx] فقط.

  • في [1] باستخدام مستكشف Windows، نقوم بنسخ مجلد مشروع [pam-v1-adonet] ونسميه [pam-v2-adonet-ajax]. ثم باستخدام Visual Web Developer، نفتح المشروع (ملف / فتح مشروع) من هذا المجلد الجديد [2]
  • إلى [3]، ونسميه
  • في خصائص المشروع الجديد، قم بتغيير اسم التجميع [4] وكذلك مساحة الاسم الافتراضية [5].

وبعد ذلك، نستبدل في ملفات [Default.aspx, Default.aspx.cs, Default.aspx.designer.cs, Global.asax, Global.asax.cs] مساحة الاسم [pam_v1] بمساحة الاسم [pam_v2] لتتوافق مع مساحة الاسم الافتراضية. على سبيل المثال، يتحول [Default.aspx] [6] إلى:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="pam_v2._Default" %>
...

سيتم تعديل الصفحة [Default.aspx] على النحو التالي:

  • إضافة مكونات Ajax في النموذج [Default.aspx] (انظر [2] أعلاه).
    • 2A: المكون <asp:ScriptManager> ضروري لأي مشروع AJAX
    • 2B: يُستخدم المكون <asp:UpdatePanel> لتحديد المنطقة المطلوب تحديثها عند قيام المستخدم بـ POST. يمنع هذا المكون إعادة تحميل الصفحة بالكامل.
    • 2C: يُستخدم المكون <asp:UpdateProgress> لعرض نص أو صورة أثناء عملية التحديث لإعلام المستخدم بذلك كما هو موضح أدناه:
  • (تابع)
    • 2D: نوع Label يسمى LabelHeureLoad والذي سيعرض الوقت الذي يتم فيه تنفيذ معالج الحدث Load للصفحة.
    • 2E: نوع Label يسمى LabelHeureSalaire والذي سيعرض الوقت الذي يتم فيه تنفيذ معالج الحدث Click على الزر [Salaire]. نريد أن نوضح أن Ajax لا يعيد تحميل الصفحة بالكامل عند النقر على الزر [Salaire]. وهذا ما تظهره لقطة الشاشة السابقة حيث يمكننا رؤية ساعتين مختلفتين في كلا الزرين Labels.

يمكن إجراء عملية Ajaxification السابقة للنموذج مباشرة في كود المصدر لـ [Default.aspx] عن طريق إضافة علامات امتدادات Ajax:


...
<body style="text-align: left" bgcolor="#ffccff">
  <h3>
    Feuille de salaire
    <asp:Label ID="LabelHeureLoad" runat="server" BackColor="#C0C000"></asp:Label></h3>
  <hr />
  <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />
    <asp:UpdatePanel runat="server" ID="UpdatePanelPam" UpdateMode="Conditional">
      <ContentTemplate>
        <div>
          <table>
            <tr>
...
            <tr>
              <td>
                <asp:DropDownList ID="ComboBoxEmployes" runat="server">
                </asp:DropDownList></td>
              <td>
                <asp:TextBox ID="TextBoxHeures" runat="server" EnableViewState="False">
                </asp:TextBox></td>
              <td>
                <asp:TextBox ID="TextBoxJours" runat="server" EnableViewState="False">
                </asp:TextBox></td>
              <td>
                <asp:Button ID="ButtonSalaire" runat="server" Text="Salaire" CausesValidation="False" /></td>
                <td>   <asp:UpdateProgress ID="UpdateProgress1" runat="server">
                  <ProgressTemplate>
                    <img src="images/indicator.gif" />
                    <asp:Label ID="Label5" runat="server" BackColor="#FF8000" EnableViewState="False"
                      Text="Calcul en cours. Patientez ...."></asp:Label>
                  </ProgressTemplate>
                </asp:UpdateProgress>
          <asp:Label ID="LabelHeureSalaire" runat="server" BackColor="#C0C000"></asp:Label></td>
            </tr>
            <tr>
...
            </tr>
          </table>
        </div>
        <br />
....
          <table>
            <tr>
              <td>
                Salaire net à payer :
              </td>
              <td align="center" bgcolor="#C0C000" height="20px">
                <asp:Label ID="LabelSN" runat="server" EnableViewState="False"></asp:Label></td>
            </tr>
          </table>
          &nbsp;</asp:Panel>
      </ContentTemplate>
    </asp:UpdatePanel>
  </form>
</body>
</html>
  • السطر 8: يجب أن يتضمن أي نموذج تم تحويله إلى Ajax العلامة <asp:ScriptManager>. هذه العلامة هي التي تسمح باستخدام مكونات Ajax الجديدة:
  • يمكن الحصول على العلامة <asp:ScriptManager> بالنقر المزدوج على المكون [ScriptManager] أعلاه. يجب التأكد من أن هذه العلامة موجودة داخل العلامة <form> في شفرة المصدر. السمة [EnablePartialRendering= "true "] في السطر 8 غائبة بشكل افتراضي. وبما أن القيمة "true" هي القيمة الافتراضية، فهي ليست ضرورية.
  • السطر 9: تسمح العلامة <asp:UpdatePanel> بتحديد مناطق الصفحة التي يجب تحديثها، عند إجراء تحديث جزئي للصفحة. تشير السمة [UpdateMode="Conditional"] إلى أن المنطقة يجب تحديثها فقط عند حدوث حدث AJAX لمكون في المنطقة. القيمة الأخرى هي [UpdateMode="Always"] وهي القيمة الافتراضية. باستخدام هذا السمة، يتم تحديث المنطقة UpdatePanel بشكل منهجي حتى لو كان حدث Ajax الذي وقع ناشئًا عن مكون في منطقة أخرى UpdatePanel. بشكل عام، هذا السلوك غير مرغوب فيه.

تسمح العلامة <asp:UpdatePanel> بعلامتين فرعيتين: <ContentTemplate> و <Triggers>.

  • تحدد العلامات <asp:ContentTemplate>، في السطرين 10 و53، منطقة الصفحة المراد تحديثها جزئيًا.
  • الأسطر 27-33: مكون Ajax <asp:UpdateProgress> يسمح بعرض نص طوال مدة تحديث الصفحة. على سبيل المثال، سيؤدي النقر على الزر [Salaire] إلى تشغيل POST في الخلفية. عندئذٍ لا يعرض المتصفح رمز الساعة الرملية، مما قد يدفع المستخدم إلى محاولة الاستمرار في استخدام النموذج. تسمح العلامة <asp:UpdateProgress> بعرض نص يحذر من أن تحديث الصفحة جارٍ. يمكن أيضًا عرض صورة. هنا، يتم عرض صورة متحركة (السطر 29) بالإضافة إلى نص (السطران 30-31):
 
  • الأسطر 28-32: تحدد العلامة <ProgressTemplate> المحتوى الذي سيتم عرضه طوال فترة تحديث المنطقة UpdatePanel التي توجد فيها العلامة UpdateProgress.
  • الأسطر 29-31: الصورة المتحركة والنص اللذان سيتم عرضهما أثناء تحديث المنطقة UpdatePanel.
  • السطر 5: يتم وضع العلامة LabelHeureLoad خارج المنطقة التي تم تفعيل Ajax عليها
  • السطر 34: يتم وضع العلامة LabelHeureSalaire داخل المنطقة التي تم تفعيل Ajax عليها

يتطور كود الصفحة [Default.aspx.cs] على النحو التالي:


    protected void Page_Load(object sender, System.EventArgs e)
    {
        // وقت كل تحميل للصفحة
        LabelHeureLoad.Text = DateTime.Now.ToString("hh:mm:ss");
        // معالجة الطلب الأولي
        if (!IsPostBack)
        {
....
}
  • السطر 4: تحديث وقت تحميل الصفحة

   protected void ButtonSalaire_Click(object sender, System.EventArgs e)
    {
        // وقت حساب الراتب
        LabelHeureSalaire.Text = DateTime.Now.ToString("hh:mm:ss");
        // يتم التحقق من البيانات
....
}
  • السطر 4: تحديث وقت حساب الراتب

لإنهاء الصفحة [Default.aspx]، يتعين علينا تضمين الصورة المتحركة المشار إليها في السطر 4 من كود المصدر التالي للصفحة:


            <td>
              <asp:UpdateProgress ID="UpdateProgress1" runat="server">
                <ProgressTemplate>
                  <img src="images/indicator.gif" />
                  <asp:Label ID="Label5" runat="server" BackColor="#FF8000" EnableViewState="False"
                    Text="Calcul en cours. Patientez ...."></asp:Label>
                </ProgressTemplate>
              </asp:UpdateProgress>
              <asp:Label ID="LabelHeureSalaire" runat="server" BackColor="#C0C000"></asp:Label>
</td>

باستخدام مستكشف Windows، نضيف الملف [images/indicator.gif] إلى مجلد المشروع [1]:

  • في [2]، نعرض جميع ملفات المشروع
  • في [3]، المجلد [images]
  • في [4]، يتم تضمين المجلد [images] في المشروع
  • في [5]، تم تضمين المجلد [images] في المشروع
  • في [6]، يتم إخفاء الملفات التي لا تشكل جزءًا من المشروع
  • في [7]، المشروع الجديد

5.3. اختبارات حل Ajax

عند طلب تنفيذ المشروع (CTRL-F5)، نحصل على الصفحة التالية:

  • في [1]، وقت تحميل الصفحة

قم بإجراء بعض الاختبارات وتأكد من أن الزر [Salaire] لا يؤدي إلى إعادة تحميل الصفحة بالكامل. يمكنك ملاحظة ذلك من خلال الوقت المعروض لمعالجة النقر على الزر [Salaire] [2] الذي يختلف عن وقت التحميل الأولي للصفحة [3]:

أعد إجراء الاختبارات بتعيين الخاصية EnablePartialRendering للمكون ScriptManager1 إلى False:

  

لاحظ أنه عندئذٍ نجد سلوك صفحة غير مستخدمة لـ ajax. يتم إعادة تحميل الصفحة بالكامل عند النقر على الزر [Salaire]. أعد إجراء الاختبارات باستخدام متصفح آخر. يهدف الاختبار متعدد المتصفحات إلى إظهار أن جافا سكريبت الذي تم إنشاؤه بواسطة مكونات الخادم ASP / AJAX يتم تفسيره بشكل صحيح من قبل المتصفحات المختلفة.

أخيرًا، دعونا نسلط الضوء على دور العلامة <asp:UpdateProgress>. في كود الإجراء [ButtonSalaire_Click] الخاص بـ [Default.aspx.cs]، أضف تعليمات توقف الإجراء لمدة 3 ثوانٍ:


using System.Threading;
   ...
protected void ButtonSalaire_Click(object sender, System.EventArgs e)
    {
        // وقت حساب الراتب
        LabelHeureSalaire.Text = DateTime.Now.ToString("hh:mm:ss");
        // في انتظار 
        Thread.Sleep(3000);
        // التحقق من البيانات
....
}

السطر 8 يجعل الخيط الذي ينفذ الإجراء [ButtonSalaire_Click] ينتظر لمدة 5 ثوانٍ. بعد ذلك، لنعد إجراء الاختبارات (بعد إعادة تعيين السمة EnablePartialRendering للمكون ScriptManager1 إلى True). هذه المرة، نرى نص [UpdateProgress] بالإضافة إلى الصورة المتحركة أثناء حساب الراتب:

5.4. Conclusion

أظهرت الدراسة السابقة أنه من الممكن تحويل تطبيقات ASP.NET الحالية إلى تطبيقات Ajax. تتجاوز ملحقات AJAX لـ ASP.NET ما سبق ذكره. ندعو القارئ إلى زيارة الموقع [http://ajax.asp.net].