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 з шару [metier], DLL, який тепер знаходиться на стороні сервера, а не на стороні клієнта.
  • Помилки 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 за допомогою Spring створюється екземпляр шару [C]. Необхідна для цього конфігурація налаштовується у [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.