Skip to content

10. The application [SimuPaie] – version 6 – client ASP.NET of a web service

10.1. The application architecture

We are evolving the client/server architecture of the NUnit test as follows:

In [1], the NUnit test is replaced by the version 8 web application. It is important to note here that this architecture includes two web servers not shown:

  • a web server that runs the [S] web service. It will run in a first instance of Visual Web Developer.
  • a web server running the [1] web client. It will run in a second instance of Visual Web Developer.

10.2. The Visual Web Developer project for client [web]

We are creating a new web project ASP.NET:

  • In [1], we select a C# web project
  • In [2], we select "Web Application ASP.NET"
  • In [3], we name the web project
  • In [4], we specify a location for this project
  • In [5], the project is created

We modify some project properties:

  • in [1], the name of the assembly that will be generated
  • in [2], the default namespace for the classes and interfaces that will be created

To build the [pam-v6-client-webservice] project, we can retrieve the [Global.asax] and [Default.aspx] files from the [pam-v4-3tier-nhibernate-multivues-monopage] web project and copy them into the [pam-v6-client-webservice] project. First, do this using Windows Explorer:

  • in [1], the folder from the [pam-v4-3tier-nhibernate-multivues-monopage] project
  • in [2], the [pam-v6-client-webservice] project folder after copying
    • the [images, pam, ressources]
    • the [Global.asax, Global.asax.cs] files
    • the files [Default.aspx, Default.aspx.cs, Default.aspx.designer.cs]
  • to [3], in Visual Studio Express, display all project files to show the newly added files
  • In [4], include the added folders and files in the project
  • in [5] the new project [pam-v6-client-webservice]

At this point, we can build the project for the first time ([6]). The following errors occur:

1
2
3
4
5
6
7
Erreur    1    Le type ou le nom d'namespace 'Dao' does not exist in namespace 'Pam' (is an assembly reference missing?) C:\temp\pam-aspnet\pam-v6-client-webserviceGlobal.asax.cs 3 11 pam-v6-client-webservice
Erreur    2    Le type ou le nom d'namespace 'Metier' does not exist in namespace 'Pam' (is an assembly reference missing?) 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'namespace 'Dao' does not exist in namespace 'Pam' (is an assembly reference missing?) c:\temp\pam-aspnet\pam-v6-client-webservicedefault.aspx.cs 5 11 pam-v6-client-webservice
Erreur    4    Le type ou le nom d'spring' namespace not found (is a using directive or assembly reference missing?) 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'namespace 'Metier' does not exist in namespace 'Pam' (is an assembly reference missing?) 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'employe' namespace not found (is a using directive or assembly reference missing?) 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'namespace 'IPamMetier' cannot be found (is a using directive or assembly reference missing?) C:\temp\pam-aspnet\pam-v6-client-webserviceGlobal.asax.cs 14 19 pam-v6-client-webservice

To understand and fix these errors, we need to look at the architecture of the web project under development:

The [pam-v6-client-webservice] project corresponds to the [web] and [1] layers in the diagram above. We can see that this layer communicates with the [C] client of the web service, a client that we will generate shortly.

  • Errors 2, 5, and 7 stem from the fact that the code for [pam-v4] referenced DLL from the [metier] layer, DLL, which is now on the server side and not on the client side.
  • Errors 1 and 3 have the same cause, but this time for DLL in the [dao] layer
  • Error 4 occurs because the code for [Global.asax] uses Spring, and our project does not reference Spring’s DLL. We will add this reference.
  • Error 6 occurs because the [Employe] class is defined in the [dao] layer, which does not exist on the client side.

Namespace errors 1, 2, 4, 5, 6, and 7 will be resolved by generating the C client for the web service. Error 3 is resolved by adding a reference to Spring’s DLL to the project. We can proceed as follows:

  • In [1], add a reference to the [pam-v6-client-webservice] project
  • In [4], we added a reference to DLL and [Spring.Core] from the [lib] folder.

After adding this reference in Spring, the project generation shows one fewer error. All other errors are due to lines of code that reference objects from the [metier] and [dao] layers, which are now on the server. We will see that these missing objects will be generated in the [C] client of the web service.

Before generating the [C] web service client, we will modify the namespace of the various classes present. They are currently in the [pam-v4] namespace. We are changing this namespace to [pam-v6]. The affected files are as follows: Default.aspx.cs, Default.aspx.designer.cs, Global.asax.cs. For example:


....
namespace pam_v6
{
  public class Global : System.Web.HttpApplication
  {
    // --- static application data ---
    public static Employe[] Employes;
    public static IPamMetier PamMetier = null;
....

Line 2: the namespace pam_v4 has been replaced by the namespace pam_v6.

In addition, the markup for the files Default.aspx and Global.asax must be modified:

  

The markup for [Default.aspx] becomes:


<%@ 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">
.....

Line 1: The Inherits attribute specifies the class name of the [Default.aspx.cs] file. We change the namespace.

The markup for [Global.asax] becomes:


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

Above, we change the namespace of the Inherits attribute.

We now generate the [C] client for the web service.

To perform the following steps, the [S] and [pam-v5-webservice] web services must be running in a separate instance of Visual Web Developer.

  • In [1], a reference to the web service [pam-v5-webservice] is added to the project [pam-v6-client-webservice]
  • In [2], the URI of the web service [pam-v5-webservice]. This is the URL of the file WSDL for this web service. In the construction of the [pam-v5-webservice] web service, we explained how to determine this Url.
  • In [3], the wizard is asked to process the WSDL file specified in [2]
  • In [4], the [Service1Soap] web service is discovered, and in [5], the remote methods it exposes are listed.
  • In [6], we set the namespace in which the classes and interfaces of the [C] client will be generated
  • We start generating the client [C]
  • In [1], the generated client. Double-click it to access its contents.
  • In [2], in the Object Explorer, the classes and interfaces of the pam_v6.WsPam namespace are displayed. This is the namespace of the generated client.
  • In [3], the class that implements the web service client.
  • In [4], the methods implemented by the client [Service1SoapClient]. Here you will find the two methods of the remote web service [5] and [6].
  • In [2], we find the images of the layer entities:
    • [metier]: FeuilleSalaire, ElementsSalaire
    • [dao]: Employee, Cotisations, Indemnites

Moving forward, keep in mind that these images of remote entities are located on the client side and in the pam_v6.WsPam namespace.

Let’s examine the methods and properties exposed by one of them:

  • In [1], we select the local class [Employe]
  • In [2], we find the properties of the remote entity [Employe] as well as private fields used for the local entity’s own purposes.

Let’s examine the code for [Global.asax.cs], which contains errors:

 
  • Lines 3 and 4 use namespaces that exist on the server but not on the client.
  • Line 13 uses a class named [Employe] for which the correct namespace has not been declared
  • Line 14 uses an interface IPamMetier that is unknown on the client.

We have already encountered similar issues in the C# client discussed earlier.

In the architecture:

  • the local [metier] layer is implemented by the [C] client of type pam_v6.WsPam.Service1SoapClient, which does not implement the IPamMetier interface even though it has methods with the same names.
  • The entities handled (Employee, Indemnites, Cotisations) by the generated client [C] are in the pam_v6.WsPam namespace

The code for [Global.asax.cs] evolves as follows:


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;
    }
  }
}

Line 24 instantiates the [C] layer using Spring. The configuration required for this instantiation is defined in [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>

Line 16: The [metier] layer is an instance of the [pam_v6.WsPam.Service1SoapClient] class, which can be found in the DLL and [pam-v6-client-webservice] layers. Recall that we configured the [pam-v6-client-webservice] project to generate this DLL.

There are still a few errors in [Default.aspx.cs]:

  • lines 5, 6: these namespaces no longer exist. The entities are now in the pam_v6 or pam_v6.WsPam namespace.
  • line 98: the generated client [C] did not inherit the [PamException] class from the [dao] layer. It could not do so because the web service does not expose this exception. We choose to replace PamException with its parent class Exception.

The code becomes:


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

Once these errors are corrected, we can run the web application:

  • in [1], the URL of the web client for the remote web service
  • in [2], the employee combo box has been populated. The data it contains comes from the web service.

We invite the reader to test this version, a copy of version.