Skip to content

10. تطبيق [SimuPaie] – الإصدار 6 – عميل ASP.NET لخدمة ويب

10.1. بنية التطبيق

نقوم بتطوير بنية العميل/الخادم لاختبار NUnit بالطريقة التالية:

في [1]، يتم استبدال الاختبار NUnit بتطبيق الويب من الإصدار 8. يجب أن نتذكر هنا أن هذه البنية تتضمن خادمين ويب غير موضحين:

  • خادم ويب يقوم بتشغيل خدمة الويب [S]. سيتم تشغيله في مثيل أول من Visual Web Developer.
  • خادم ويب يقوم بتشغيل عميل الويب [1]. وسيتم تشغيله في مثيل ثانٍ من Visual Web Developer.

10.2. مشروع Visual Web Developer للعميل [web]

نقوم بإنشاء مشروع ويب جديد ASP.NET:

  • في [1]، نختار مشروع ويب بلغة C#
  • في [2]، نختار "تطبيق ويب ASP.NET"
  • في [3]، نسمي مشروع الويب
  • في [4]، نحدد موقعًا لهذا المشروع
  • في [5]، تم إنشاء المشروع

نقوم بتعديل بعض خصائص المشروع:

  • في [1]، اسم التجميع الذي سيتم إنشاؤه
  • في [2]، مساحة الأسماء الافتراضية للفئات والواجهات التي سيتم إنشاؤها

لبناء المشروع [pam-v6-client-webservice]، يمكننا استرداد الملفات [Global.asax] و [Default.aspx] من مشروع الويب [pam-v4-3tier-nhibernate-multivues-monopage] ونسخها إلى المشروع [pam-v6-client-webservice]. يتم ذلك باستخدام مستكشف Windows أولاً:

  • إلى [1]، ومجلد مشروع [pam-v4-3tier-nhibernate-multivues-monopage]
  • إلى [2]، ومجلد المشروع [pam-v6-client-webservice] بعد النسخ
    • مجلدات [images, pam, ressources]
    • ملفات [Global.asax, Global.asax.cs]
    • ملفات [Default.aspx, Default.aspx.cs, Default.aspx.designer.cs]
  • إلى [3]، في Visual Studio Express، نقوم بعرض جميع ملفات المشروع، لإظهار الملفات المضافة حديثًا
  • في [4]، يتم تضمين المجلدات والملفات المضافة في المشروع
  • في [5] المشروع الجديد [pam-v6-client-webservice]

في هذه المرحلة، يمكن إنشاء المشروع للمرة الأولى [6]. تظهر الأخطاء التالية:

1
2
3
4
5
6
7
Erreur    1    Le type ou le nom d'espace de noms 'Dao' n'existe pas dans l'espace de noms 'Pam' (une référence d'assembly est-elle manquante ?)    C:\temp\pam-aspnet\pam-v6-client-webservice\Global.asax.cs    3    11    pam-v6-client-webservice
Erreur    2    Le type ou le nom d'espace de noms 'Metier' n'existe pas dans l'espace de noms 'Pam' (une référence d'assembly est-elle manquante ?)    C:\temp\pam-aspnet\pam-v6-client-webservice\Global.asax.cs    4    11    pam-v6-client-webservice
Erreur    3    Le type ou le nom d'espace de noms 'Dao' n'existe pas dans l'espace de noms 'Pam' (une référence d'assembly est-elle manquante ?)    c:\temp\pam-aspnet\pam-v6-client-webservice\default.aspx.cs    5    11    pam-v6-client-webservice
Erreur    4    Le type ou le nom d'espace de noms 'Spring' est introuvable (une directive using ou une référence d'assembly est-elle manquante ?)    C:\temp\pam-aspnet\pam-v6-client-webservice\Global.asax.cs    6    7    pam-v6-client-webservice
Erreur    5    Le type ou le nom d'espace de noms 'Metier' n'existe pas dans l'espace de noms 'Pam' (une référence d'assembly est-elle manquante ?)    c:\temp\pam-aspnet\pam-v6-client-webservice\default.aspx.cs    6    11    pam-v6-client-webservice
Erreur    6    Le type ou le nom d'espace de noms 'Employe' est introuvable (une directive using ou une référence d'assembly est-elle manquante ?)    C:\temp\pam-aspnet\pam-v6-client-webservice\Global.asax.cs    13    19    pam-v6-client-webservice
Erreur    7    Le type ou le nom d'espace de noms 'IPamMetier' est introuvable (une directive using ou une référence d'assembly est-elle manquante ?)    C:\temp\pam-aspnet\pam-v6-client-webservice\Global.asax.cs    14    19    pam-v6-client-webservice

لفهم هذه الأخطاء وتصحيحها، يجب العودة إلى بنية مشروع الويب قيد الإنشاء:

المشروع [pam-v6-client-webservice] هو الطبقة [web] [1] في المخطط أعلاه. نرى أن هذه الطبقة تتواصل مع عميل خدمة الويب [C]، وهو عميل سنقوم بإنشائه قريبًا.

  • تعود الأخطاء 2 و5 و7 إلى أن كود [pam-v4] كان يشير إلى DLL من الطبقة [metierDLL التي أصبحت الآن على جانب الخادم وليس على جانب العميل.
  • الأخطاء 1 و 3 لها نفس السبب، ولكن هذه المرة بالنسبة لـ DLL من الطبقة [dao]
  • الخطأ 4 ناتج عن أن كود [Global.asax] يستخدم Spring وأن مشروعنا لا يشير إلى DLL من Spring. سنقوم بإضافة هذا الإشارة.
  • الخطأ 6 ناتج عن أن الفئة [Employe] محددة في الطبقة [dao] التي لا توجد على جانب العميل.

سيتم حل أخطاء مساحة الاسم 1 و2 و4 و5 و6 و7 من خلال إنشاء عميل C لخدمة الويب. يتم حل الخطأ 3 بإضافة مرجع إلى المشروع على DLL من Spring. يمكننا القيام بما يلي:

  • في [1]، نضيف مرجعًا إلى مشروع [pam-v6-client-webservice]
  • في [4]، تمت إضافة مرجع إلى DLL [Spring.Core] من المجلد [lib].

بعد إضافة هذه الإشارة في Spring، أصبح إنشاء المشروع يظهر خطأً أقل. جميع الأخطاء الأخرى ناتجة عن أسطر كود تشير إلى كائنات في الطبقات [metier] و [dao] الموجودة الآن على الخادم. سنرى أن هذه الكائنات المفقودة سيتم إنشاؤها في عميل [C] لخدمة الويب.

قبل إنشاء عميل الخدمة الويب [C]، سنقوم بتعديل مساحة أسماء الفئات المختلفة الموجودة. وهي موجودة حاليًا في مساحة الأسماء [pam-v4]. سنقوم بتغيير مساحة الاسم هذه إلى [pam-v6]. الملفات المعنية هي التالية: Default.aspx.cs، Default.aspx.designer.cs، Global.asax.cs. على سبيل المثال:


....
namespace pam_v6
{
  public class Global : System.Web.HttpApplication
  {
    // --- بيانات التطبيق الثابتة ---
    public static Employe[] Employes;
    public static IPamMetier PamMetier = null;
....

السطر 2، تم استبدال مساحة الاسم pam_v4 بمساحة الاسم pam_v6.

بالإضافة إلى ذلك، يجب تعديل ترميز الملفات: Default.aspx و Global.asax:

  

يصبح ترميز [Default.aspx] كما يلي:


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="pam_v6.PagePam" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
.....

السطر 1، يشير السمة Inherits إلى اسم فئة الملف [Default.aspx.cs]. يتم تغيير مساحة الأسماء.

يصبح ترميز [Global.asax] كما يلي:


<%@ Application Codebehind="Global.asax.cs" Inherits="pam_v6.Global" Language="C#" %>

فيما سبق، يتم تغيير مساحة اسم السمة Inherits.

نقوم الآن بإنشاء عميل [C] لخدمة الويب.

لإجراء العمليات التالية، يجب تشغيل خدمة الويب [S] [pam-v5-webservice] في مثيل آخر من Visual Web Developer.

  • في [1]، نضيف إلى المشروع [pam-v6-client-webservice]، مرجعًا إلى خدمة الويب [pam-v5-webservice]
  • في [2]، يتم إضافة URI لخدمة الويب [pam-v5-webservice]. وهو URL لملف WSDL لهذه الخدمة. في بناء خدمة الويب [pam-v5-webservice]، تم توضيح كيفية معرفة عنوان URL هذا.
  • في [3]، يُطلب من المساعد استغلال الملف WSDL المشار إليه في [2]
  • في [4]، تم اكتشاف خدمة الويب [Service1Soap] وفي [5] الطرق البعيدة التي تعرضها.
  • في [6]، يتم تحديد مساحة الأسماء التي سيتم فيها إنشاء فئات وواجهات عميل [C]
  • يتم بدء إنشاء العميل [C]
  • في [1]، العميل الذي تم إنشاؤه. انقر عليه مرتين للوصول إلى محتواه.
  • في [2]، في مستكشف الكائنات، يتم عرض الفئات والواجهات الخاصة بمساحة الاسم pam_v6.WsPam. هذه هي مساحة الاسم للعميل الذي تم إنشاؤه.
  • في [3]، الفئة التي تنفذ عميل خدمة الويب.
  • في [4]، الطرق التي ينفذها العميل [Service1SoapClient]. نجد هنا طريقتي خدمة الويب البعيدة [5] و [6].
  • في [2]، نجد صور كيانات الطبقات:
    • [metier]: FeuilleSalaire، ElementsSalaire
    • [dao]: Employe، Cotisations، Indemnites

فيما يلي، يجب تذكر أن صور الكيانات البعيدة هذه موجودة على جانب العميل وفي مساحة الاسم pam_v6.WsPam.

دعونا نلقي نظرة على الطرق والخصائص التي تعرضها إحداها:

  • في [1]، يتم تحديد الفئة المحلية [Employe]
  • في [2]، نجد خصائص الكيان البعيد [Employe] بالإضافة إلى الحقول الخاصة المستخدمة لاحتياجات الكيان المحلي الخاصة.

دعونا نفحص كود [Global.asax.cs] الذي يحتوي على أخطاء:

  • تستخدم السطران 3 و 4 مساحات أسماء موجودة على الخادم ولكنها غير موجودة لدى العميل.
  • يستخدم السطر 13 فئة [Employe] لم يتم الإعلان عن مساحة الاسم الصحيحة لها
  • السطر 14 يستخدم واجهة IPamMetier غير معروفة لدى العميل.

لقد واجهنا بالفعل مشاكل مماثلة في عميل C# الذي تمت دراسته سابقًا.

في البنية:

  • يتم تنفيذ الطبقة المحلية [metier] بواسطة العميل [C] من النوع pam_v6.WsPam.Service1SoapClient الذي لا ينفذ الواجهة IPamMetier حتى وإن كان يحتوي على طرق تحمل نفس الأسماء.
  • الكيانات التي تمت معالجتها (Employe، Indemnites، Cotisations) بواسطة العميل [C] الذي تم إنشاؤه موجودة في مساحة الأسماء pam_v6.WsPam

يتطور كود [Global.asax.cs] على النحو التالي:


using System;
using System.Collections.Generic;
using Pam.Web;
using Spring.Context.Support;
using pam_v6.WsPam;

namespace pam_v6
{
  public class Global : System.Web.HttpApplication
  {
    // --- بيانات التطبيق الثابتة ---
    public static Employe[] Employes;
    public static Service1SoapClient PamMetier = null;
    public static string Msg;
    public static bool Erreur = false;

    // بدء تشغيل التطبيق
    public void Application_Start(object sender, EventArgs e)
    {
      // تشغيل ملف التكوين
      try
      {
        // إنشاء مثيل الطبقة [metier]
        PamMetier = ContextRegistry.GetContext().GetObject("pammetier") as Service1SoapClient;
        // قائمة مبسطة بالموظفين
        Employes = PamMetier.GetAllIdentitesEmployes();
        // تم النجاح
        Msg = "Base chargée...";
      }
      catch (Exception ex)
      {
        // تسجيل الخطأ
        Msg = string.Format("L'erreur suivante s'est produite lors de l'accès à la base de données : {0}", ex);
        Erreur = true;
      }
    }

    public void Session_Start(object sender, EventArgs e)
    {
      // وضع قائمة محاكاة فارغة في الجلسة 
      List<Simulation> simulations = new List<Simulation>();
      Session["simulations"] = simulations;
    }
  }
}

السطر 24 يقوم بإنشاء مثيل للطبقة [C] باستخدام Spring. يتم إجراء التكوين اللازم لهذا الإنشاء في [web.config]:


<configSections>
      <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
 ...
      </sectionGroup>
      <sectionGroup name="spring">
        <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
        <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
      </sectionGroup>
    </configSections>

  <spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
      <objects xmlns="http://www.springframework.net">
        <object id="pammetier" type="pam_v6.WsPam.Service1SoapClient,pam-v6-client-webservice"/>
      </objects>
</spring>

في السطر 16، الطبقة [metier] هي مثيل للفئة [pam_v6.WsPam.Service1SoapClient] التي ستوجد في DLL [pam-v6-client-webservice]. نذكر أننا قمنا بتكوين المشروع [pam-v6-client-webservice] لينتج هذا DLL.

لا تزال هناك بعض الأخطاء في [Default.aspx.cs]:

  • السطران 5 و6: لم تعد مساحات الأسماء هذه موجودة. أصبحت الكيانات الآن في مساحة الاسم pam_v6 أو pam_v6.WsPam.
  • السطر 98: لم يقم العميل الذي تم إنشاؤه [C] باسترداد الفئة [PamException] من الطبقة [dao]. لم يكن بإمكانه ذلك لأن خدمة الويب لا تعرض هذا الاستثناء. يتم اختيار استبدال PamException بفئته الأصلية Exception.

يصبح الكود:


...
using System.Web.UI.WebControls;
using pam_v6.WsPam;

namespace pam_v6
{

  public partial class PagePam : Page
  {
...

...
      try
      {
        feuillesalaire = Global.PamMetier.GetSalaire(DropDownListEmployes.SelectedValue, HeuresTravaillées, JoursTravaillés);
      }
      catch (Exception ex)
      {
...

بمجرد تصحيح هذه الأخطاء، يمكننا تشغيل تطبيق الويب:

  • في [1]، و URL لعميل الويب الخاص بخدمة الويب البعيدة
  • في [2]، تم ملء قائمة الموظفين. البيانات التي تحتوي عليها تأتي من خدمة الويب.

ندعو القارئ إلى اختبار هذه النسخة 6 من النسخة 4.