10. اپلیکیشن [SimuPaie] – نسخهٔ ۶ – کلاینت ASP.NET یک سرویس وب
10.1. معماری برنامه
ما معماری کلاینت/سرور تست NUnit را به شرح زیر ارتقا میدهیم:
![]() |
در [1]، تست NUnit با اپلیکیشن وب نسخه ۸ جایگزین شده است. توجه به این نکته مهم است که این معماری شامل دو وبسرور است که نشان داده نشدهاند:
- یک سرور وب که سرویس وب [S] را اجرا میکند. این در اولین نمونه از Visual Web Developer اجرا خواهد شد.
- یک سرور وب که کلاینت وب [1] را اجرا میکند. این در نمونه دوم Visual Web Developer اجرا خواهد شد.
10.2. پروژه Visual Web Developer برای کلاینت [web]
ما در حال ایجاد یک پروژه وب جدید، ASP.NET هستیم:
![]() |
- در [1]، یک پروژه وب C# را انتخاب میکنیم
- در [2]، «Web Application 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] کپی کنیمابتدا این کار را با استفاده از اکتشافگر فایل ویندوز انجام دهید:
![]() |
- به [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]، در ویژوال استودیو اکسپرس، تمام فایلهای پروژه را نمایش دهید تا فایلهای تازه اضافه شده مشخص شوند
- در [4]، پوشهها و فایلهای اضافه شده را در پروژه وارد کنید
![]() |
- در [5]، پروژه جدید [pam-v6-client-webservice]
در این مرحله، پروژه میتواند برای اولین بار تولید شود: [6]. خطاهای زیر رخ میدهند:
برای درک و اصلاح این خطاها، باید به معماری پروژه وب در حال توسعه نگاهی بیندازیم:
![]() |
پروژه [pam-v6-client-webservice] با لایههای [web] و [1] در نمودار بالا مطابقت دارد. میتوانیم ببینیم که این لایه با کلاینت سرویس وب [C] ارتباط برقرار میکند، کلاینتی که به زودی آن را ایجاد خواهیم کرد.
- خطاهای ۲، ۵ و ۷ به این دلیل رخ میدهند که کد مربوط به [pam-v4]، لایه [metier] را برای فراخوانی DLL استفاده کرده است، DLL، که اکنون در سمت سرور است نه سمت کلاینت.
- خطاهای ۱ و ۳ علت یکسانی دارند، اما این بار برای DLL در لایه [dao]
- خطای ۴ به این دلیل است که کد مربوط به [Global.asax] از Spring استفاده میکند و پروژه ما به DLL مربوط به Spring ارجاع نمیدهد. ما این ارجاع را اضافه خواهیم کرد.
- خطای ۶ به این دلیل رخ میدهد که کلاس [Employe] در لایه [dao] تعریف شده است که در سمت کلاینت وجود ندارد.
خطاهای فضای نام ۱، ۲، ۴، ۵، ۶ و ۷ با تولید کلاینت C برای سرویس وب برطرف خواهند شد. خطای ۳ با افزودن یک مرجع به DLL اسپرینگ به پروژه برطرف میشود. میتوانیم به شرح زیر ادامه دهیم:
![]() |
- در [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;
....
در خط ۲، فضای نام 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">
.....
خط ۱: ویژگی 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] اضافه کنید
- در [2]، URI سرویس وب [pam-v5-webservice]. این URL فایل WSDL برای این سرویس وب است. در بخش راهاندازی سرویس وب [pam-v5-webservice]، نحوهٔ یافتن این URL را توضیح دادیم.
- در [3]، به ویزارد دستور داده میشود تا فایل WSDL را که در [2] مشخص شده است، پردازش کند.
- در [4]، سرویس وب [Service1Soap] کشف میشود و در [5]، متدهای راه دوری که ارائه میدهد فهرست شدهاند.
- در [6]، فضای نامی را مشخص میکنیم که کلاسها و رابطهای کلاینت [C] در آن تولید خواهند شد
- ایجاد کلاینت [C] آغاز میشود
![]() |
- در [1]، کلاینت تولیدشده. برای دسترسی به محتویات آن روی آن دوبار کلیک کنید.
- در [2]، در Object Explorer، کلاسها و رابطهای namespace pam_v6.WsPam نمایش داده میشوند. این namespace مربوط به کلاینت تولید شده است.
- در [3]، کلاسی که مشتری سرویس وب را پیادهسازی میکند.
- در [4]، متدهای پیادهسازیشده توسط کلاینت [Service1SoapClient]. اینها شامل دو متد سرویس وب راه دور هستند: [5] و [6].
- در [2]، تصاویر ویژگیهای لایه به شرح زیر است:
- [metier]: FeuilleSalaire, ElementsSalaire
- [dao]: Employe, Cotisations, Indemnites
در ادامه، مهم است به خاطر داشته باشیم که این تصاویر از اشیاء راه دور در سمت کلاینت و در فضای نام pam_v6.WsPam قرار دارند.
بیایید روشها و ویژگیهای ارائه شده توسط یکی از آنها را بررسی کنیم:
![]() |
- در [1]، کلاس محلی [Employe] انتخاب میشود
- در [2]، ما ویژگیهای موجودیت راه دور [Employe] و همچنین فیلدهای خصوصی را که برای اهداف خود موجودیت محلی استفاده میشوند، مییابیم.
بیایید کد مربوط به [Global.asax.cs] را که حاوی خطاها است، بررسی کنیم:
![]() |
- خطوط ۳ و ۴ از فضاهای نامی استفاده میکنند که در سرور وجود دارند اما در کلاینت وجود ندارند.
- خط ۱۳ از کلاسی به نام [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;
}
}
}
خط ۲۴ لایه [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>
در خط ۱۶، لایه [metier] یک نمونه از کلاس [pam_v6.WsPam.Service1SoapClient] است که میتوان آن را در DLL و [pam-v6-client-webservice] یافت. به عنوان یادآوری، ما پروژه [pam-v6-client-webservice] را برای تولید این DLL پیکربندی کردهایم.
هنوز چند خطا در [Default.aspx.cs] وجود دارد:
![]() | ![]() |
- خطوط ۵ و ۶: این فضاهای نام دیگر وجود ندارند. این انتیتهها اکنون در فضای نام pam_v6 یا pam_v6.WsPam قرار دارند.
- خط ۹۸: کلاینت تولیدشده [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]، لیست کشویی کارکنان پر شده است. دادههای موجود در آن از سرویس وب تأمین میشوند.
از خواننده دعوت میشود تا این نسخه ۶ را که کپی نسخه ۴ است، آزمایش کند.

















