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]. ستظهر لك الأخطاء التالية:
لفهم هذه الأخطاء وإصلاحها، نحتاج إلى النظر في بنية مشروع الويب قيد التطوير:
![]() |
مشروع [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.

















