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 لعميل [الويب]

نقوم بإنشاء مشروع ويب 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, resources]
    • الملفات [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] هو الطبقة [الويب] [1] في الرسم البياني أعلاه. يمكننا أن نرى أن هذه الطبقة تتواصل مع عميل خدمة الويب [C]، وهو عميل سنقوم بإنشائه قريبًا.

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

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

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

بعد إضافة هذا المرجع إلى Spring، يظهر إنشاء المشروع خطأً أقل. جميع الأخطاء الأخرى ناتجة عن أسطر كود تشير إلى كائنات من طبقات [business] و[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
  {
    // --- static application data ---
    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-v5-webservice] إلى المشروع [pam-v6-client-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]، تظهر مخططات الكيانات الخاصة بالطبقات:
    • [business] : Payroll, PayrollItems
    • [DAO]: الموظف، الاشتراكات، البدلات

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

دعونا نفحص الطرق والخصائص التي يعرضها أحدها:

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

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

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

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

في البنية:

  • يتم تنفيذ الطبقة [التجارية] المحلية بواسطة العميل [C] من النوع pam_v6.WsPam.Service1SoapClient، الذي لا ينفذ واجهة IPamMetier على الرغم من أنه يحتوي على طرق تحمل نفس الأسماء.
  • توجد الكيانات التي يتعامل معها العميل [C] الذي تم إنشاؤه (Employee، Benefits، Contributions) في مساحة اسم 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
  {
    // --- static application data ---
    public static Employe[] Employes;
    public static Service1SoapClient PamMetier = null;
    public static string Msg;
    public static bool Erreur = false;
 
    // application startup
    public void Application_Start(object sender, EventArgs e)
    {
      // using the configuration file
      try
      {
        // instantiation layer [metier]
        PamMetier = ContextRegistry.GetContext().GetObject("pammetier") as Service1SoapClient;
        // simplified list of employees
        Employes = PamMetier.GetAllIdentitesEmployes();
        // we succeeded
        Msg = "Base chargée...";
      }
      catch (Exception ex)
      {
        // we note the error
        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)
    {
      // put an empty simulation list in the session 
      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: طبقة [business] هي مثيل لفئة [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.