Skip to content

10. [SimuPaie] uygulaması – sürüm 6 – bir web hizmetinin ASP.NET istemcisi

10.1. Uygulamanın mimarisi

NUnit testinin istemci/sunucu mimarisini şu şekilde geliştiriyoruz:

[1]'te, NUnit testi, sürüm 8'in web uygulamasıyla değiştirilmiştir. Burada, bu mimarinin gösterilmeyen iki web sunucusu içerdiğini unutmamak gerekir:

  • [S] web hizmetini çalıştıran bir web sunucusu. Bu, Visual Web Developer'ın ilk örneğinde çalışacaktır.
  • [1] web istemcisini çalıştıran bir web sunucusu. Bu, Visual Web Developer'ın ikinci bir örneğinde çalışacaktır.

10.2. [web] istemcisinin Visual Web Developer projesi

ASP.NET adlı yeni bir web projesi oluşturuyoruz:

  • [1]'te, C# ile bir web projesi seçiyoruz
  • [2]'te "ASP.NET Web Uygulaması"nı seçiyoruz
  • [3]'te, web projesine bir ad veriyoruz
  • [4]'te, bu proje için bir konum belirtiyoruz
  • [5] dosyasında, proje oluşturuldu

Projenin bazı özelliklerini değiştiriyoruz:

  • [1]'te, oluşturulacak derlemenin adı
  • [2] olarak, oluşturulacak sınıflar ve arayüzler için varsayılan ad alanı

[pam-v6-client-webservice] projesini derlemek için, [pam-v4-3tier-nhibernate-multivues-monopage] web projesinden [Global.asax] ve [Default.aspx] dosyalarını alıp [pam-v6-client-webservice] projesine kopyalayabiliriz. Bunu öncelikle Windows Dosya Gezgini ile yapabiliriz:

  • dosyasını [1] projesine, [pam-v4-3tier-nhibernate-multivues-monopage]
  • 'i [2]'e, [pam-v6-client-webservice] proje klasörünü de kopyalama işleminden sonra
    • [images, pam, ressources]
    • [Global.asax, Global.asax.cs] dosyaları
    • [Default.aspx, Default.aspx.cs, Default.aspx.designer.cs] dosyaları
  • [3]'e kopyalandıktan sonra, Visual Studio Express'te projenin tüm dosyalarını görüntüleyerek yeni eklenen dosyaları ortaya çıkarırız
  • [4] dosyasına, eklenen klasörleri ve dosyaları projeye dahil ediyoruz
  • [5]'te yeni proje [pam-v6-client-webservice]

Bu aşamada, projeyi ilk kez derleyebiliriz: [6]. Aşağıdaki hatalarla karşılaşılır:

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

Bu hataları anlamak ve düzeltmek için, geliştirilmekte olan web projesinin mimarisine geri dönmek gerekir:

[pam-v6-client-webservice] projesi, yukarıdaki şemada [web] ve [1] katmanlarını oluşturmaktadır. Bu katmanın, web hizmetinin [C] istemcisiyle iletişim kurduğu görülüyor; bu istemciyi yakında oluşturacağız.

  • 2, 5 ve 7 numaralı hatalar, [pam-v4] kodunun, [metier] katmanındaki DLL'e referans vermesinden kaynaklanmaktadır; DLL katmanında yer alıyordu; bu katman artık istemci tarafında değil, sunucu tarafındadır.
  • 1 ve 3 numaralı hataların nedeni aynıdır, ancak bu sefer [dao] katmanındaki DLL ile ilgilidir
  • Hata 4, [Global.asax] kodunun Spring kullandığından ve projemizin Spring'in DLL'sine referans vermediğinden kaynaklanmaktadır. Bu referansı ekleyeceğiz.
  • Hata 6, [Employe] sınıfının, istemci tarafında mevcut olmayan [dao] katmanında tanımlanmış olmasından kaynaklanmaktadır.

1, 2, 4, 5, 6 ve 7 numaralı ad alanı hataları, web hizmetinin C istemcisinin oluşturulmasıyla çözülecektir. 3 numaralı hata ise projeye Spring'in DLL sınıfına bir referans eklenerek çözülür. Aşağıdaki şekilde ilerleyebiliriz:

  • [1]'te, projeye [pam-v6-client-webservice] referansı eklenir
  • [4]'te, [lib] klasöründeki DLL ve [Spring.Core]'e bir referans eklenmiştir.

Spring'e bu referans eklendikten sonra, proje oluşturma işleminde bir hata azaldı. Diğer tüm hatalar, artık sunucuda bulunan [metier] ve [dao] katmanlarındaki nesnelere referans veren kod satırlarından kaynaklanmaktadır. Göreceğiz ki, bu eksik nesneler web hizmetinin [C] istemcisinde oluşturulacaktır.

Web hizmetinin [C] istemcisini oluşturmadan önce, mevcut çeşitli sınıfların ad alanını değiştireceğiz. Bu sınıflar şu anda [pam-v4] ad alanında bulunmaktadır. Bu ad alanını [pam-v6] olarak değiştiriyoruz. İlgili dosyalar şunlardır: Default.aspx.cs, Default.aspx.designer.cs, Global.asax.cs. Örneğin:


....
namespace pam_v6
{
  public class Global : System.Web.HttpApplication
  {
    // --- uygulamanın statik verileri ---
    public static Employe[] Employes;
    public static IPamMetier PamMetier = null;
....
  1. satırda, pam_v4 ad alanı, pam_v6 ad alanıyla değiştirilmiştir.

Ayrıca, Default.aspx ve Global.asax dosyalarının etiketleri de değiştirilmelidir:

  

[Default.aspx] dosyasının etiketlemesi şu şekilde olur:


<%@ 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. satırda, Inherits özniteliği, [Default.aspx.cs] dosyasının sınıf adını belirtir. Ad alanı değiştirilir.

[Global.asax] etiketlemesi şu şekilde olur:


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

Yukarıda, Inherits özniteliğinin ad alanı değiştirilmiştir.

Şimdi web hizmetinin [C] istemcisini oluşturuyoruz.

Aşağıdaki işlemleri gerçekleştirmek için, [S] ve [pam-v5-webservice] web hizmetlerinin başka bir Visual Web Developer örneğinde çalıştırılması gerekir.

  • [1]'te, [pam-v6-client-webservice] projesine, [pam-v5-webservice] web hizmetine bir referans eklenir
  • [2]'te, [pam-v5-webservice] web hizmetinin URI'i. Bu, söz konusu web hizmetinin WSDL dosyasının URL'idir. [pam-v5-webservice] web hizmetinin yapısında, bu URL'yi nasıl bulacağımız belirtilmiştir.
  • [3]'te, asistandan [2]'te belirtilen WSDL dosyasını
  • [4]'te, [Service1Soap] web hizmeti keşfedilir ve [5]'te bu hizmetin sunduğu uzaktan yöntemler gösterilir.
  • [6]'te, [C] istemcisinin sınıflarının ve arayüzlerinin oluşturulacağı ad alanı belirlenir
  • [C] istemcisinin oluşturulması başlatılır
  • [1] dosyasında, oluşturulan istemci bulunur. İçeriğine erişmek için bu dosyaya çift tıklayın.
  • [2]'te, nesne gezgininde pam_v6.WsPam ad alanına ait sınıflar ve arayüzler görüntülenir. Bu, oluşturulan istemcinin ad alanıdır.
  • [3]'te, web hizmeti istemcisini uygulayan sınıf bulunur.
  • [4]'te, [Service1SoapClient] istemcisi tarafından uygulanan yöntemler bulunur. Burada, [5] ve [6] adlı iki uzak web hizmeti yöntemi yer alır.
  • [2] dosyasında, katmanlardaki nesnelerin görüntüleri bulunur:
    • [metier]: FeuilleSalaire, ElementsSalaire
    • [dao]: Employe, Cotisations, Indemnites

Bundan sonra, bu uzak varlıkların görüntülerinin istemci tarafında ve pam_v6.WsPam ad alanında bulunduğunu unutmamak gerekir.

Bunlardan birinin sunduğu yöntem ve özellikleri inceleyelim:

  • [1]'te, yerel [Employe] sınıfı seçilir
  • [2]'te, uzak [Employe] varlığının özelliklerinin yanı sıra yerel varlığın kendi ihtiyaçları için kullanılan özel alanlar da bulunur.

Hatalar içeren [Global.asax.cs] kodunu inceleyelim:

 
  • 3. ve 4. satırlarda, sunucuda mevcut olan ancak istemcide bulunmayan ad alanları kullanılmaktadır.
  • 13. satırda, doğru ad alanı bildirilmemiş bir [Employe] sınıfı kullanılmaktadır
  • 14. satırda, istemcide bilinmeyen bir IPamMetier arayüzü kullanılmaktadır.

Daha önce incelediğimiz C# istemcisinde de benzer sorunlarla karşılaşmıştık.

Mimari içinde:

  • yerel [metier] katmanı, pam_v6.WsPam.Service1SoapClient türündeki [C] istemcisi tarafından uygulanmaktadır; bu istemci, aynı adlı yöntemlere sahip olmasına rağmen IPamMetier arayüzünü uygulamamaktadır.
  • İşlenen varlıklar (Employe, Indemnites, Cotisations), oluşturulan [C] istemcisi tarafından pam_v6.WsPam ad alanında yer almaktadır

[Global.asax.cs] kodunda aşağıdaki değişiklikler yapılmıştır:


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
  {
    // --- uygulamanın statik verileri ---
    public static Employe[] Employes;
    public static Service1SoapClient PamMetier = null;
    public static string Msg;
    public static bool Erreur = false;

    // uygulamanın başlatılması
    public void Application_Start(object sender, EventArgs e)
    {
      // yapılandırma dosyasının işlenmesi
      try
      {
        // [metier] katmanının örneklenmesi
        PamMetier = ContextRegistry.GetContext().GetObject("pammetier") as Service1SoapClient;
        // çalışanların basitleştirilmiş listesi
        Employes = PamMetier.GetAllIdentitesEmployes();
        // başarılı
        Msg = "Base chargée...";
      }
      catch (Exception ex)
      {
        // hata kaydedildi
        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)
    {
      // oturuma boş bir simülasyon listesi ekleniyor 
      List<Simulation> simulations = new List<Simulation>();
      Session["simulations"] = simulations;
    }
  }
}
  1. satırda, Spring aracılığıyla [C] katmanı örneklenir. Bu örneklendirme için gerekli yapılandırma, [web.config] içinde yapılır:

<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>
  1. satırda, [metier] katmanı, [pam_v6.WsPam.Service1SoapClient] sınıfının bir örneğidir ve bu sınıf, DLL ile [pam-v6-client-webservice] içinde bulunur. Hatırlanacağı üzere, [pam-v6-client-webservice] projesini bu DLL'i oluşturacak şekilde yapılandırmıştık.

[Default.aspx.cs] dosyasında hâlâ birkaç hata bulunmaktadır:

  • 5. ve 6. satırlar: Bu ad alanları artık mevcut değil. Varlıklar artık pam_v6 veya pam_v6.WsPam ad alanlarında yer almaktadır.
  • 98. satır: Oluşturulan [C] istemcisi, [dao] katmanındaki [PamException] sınıfını devralmamıştır. Web hizmeti bu istisnayı sunmadığı için bunu yapamazdı. PamException'i üst sınıfı olan Exception ile değiştirmeye karar veriyoruz.

Kod şu şekilde olur:


...
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)
      {
...

Bu hatalar düzeltildikten sonra web uygulamasını çalıştırabiliriz:

  • [1]'te, uzak web hizmetinin web istemcisi olan URL'te
  • [2]'te, çalışanlar listesi doldurulmuştur. İçerdiği veriler web hizmetinden gelmektedir.

Okuyucuyu, sürüm 4'ün bu 6. kopyasını denemeye davet ediyoruz.