asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search








Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

SOAP Test Harness
By Craig Emilio Probus
Rating: 4.4 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    Web Services are an integral part of a new technology and set of standards and protocols (including SOAP and XSD) designed to enhance and simplify the interaction of heterogeneous and remote software components across the Internet and within intranets. Microsoft has embraced these new standards and has made them an integral part of its .NET strategy both in its Visual Studio.NET (VS.NET) development environment and the .NET Framework in order to facilitate the use of Web Services.

    My project team is currently developing a distributed .NET application using Web Services as a basis for a component model. Because of this intensive use of Web services, we needed to facilitate the testing process of our components for both component consumers and component developers. The SOAP Test Harness was created for this end. Although there is a test harness included in VS.NET, it uses an HTTP "Get" to invoke the methods of a Web Service and not an HTTP Post using the SOAP standard. The Simple Object Access Protocol (SOAP) standard defines an eXtensible Markup Language (XML) structure for a message (the "SOAP:Envelope") and the contents of the message (the "SOAP:Body"). Due to this limitation, we could not verify that even if the method worked properly with the HTTP Get invocation, it would work with a SOAP message. A testing program could have been developed for each Web Service by individual programmers, but for the size of this project, maintenance, and other reasons, it was deemed beneficial to develop a generic program to test the various Web Services. In addition, the lessons learned during the development of the test harness were useful for the ongoing development of our Web Services.

    The SOAP Test Harness is an ASP.NET application created in VS.NET that allows technical and functional personnel to test Web Services. The SOAP Test Harness takes advantage of many of the .NET Framework classes to effectively use XML, XPath, and the operating system to access the directory structure. XPath is an XSL language for addressing parts of an XML document. XPath was designed to be used by eXtensible Stylesheet Language Transformations (XSLT), but can now be used to make queries against an XML document. This article will present examples beyond XML and XSL, such as creating files and accessing external applications.

    I also wanted to ensure that programmers developing remotely could access the Web Services Description Language (WSDL --pronounced whiz-dull) document without error. The WSDL document acts as a contract for a Web Service and describes the interfaces, how to access the methods, and the parameters for the methods. The WSDL document is an XML document that uses XML Schema (XSD) to define primitive and object data types. XSD Schema describes the data structures exposed by Web Services. This allows the developer to define complex data types using XSD Schemas, supporting a richer set of data types. If the Web Service is created using VS.NET, then the WSDL document is automatically generated. For clarification, an explanation of the most important tags of the WSDL document follows:

    • <definitions>: the root element of the WSDL document.
    • <service>: a child of the <definitions> element, it has an attribute "name" that defines the name of the Web Service.
    • <soap:address>: a grandchild of the <service> element, it has an attribute "location" that specifies the URL of the Web Service.
    • <message>: describes the request and response messages. Two are needed for each method that will be exposed through the Web Service. It is a child node of the <definitions> element.
    • <part>: a child of the <message> element, it describes the parameters or return values in the SOAP call.
    • <types>: describes the data types and number of parameters or return values for a method call. It is a child element of the <definitions> element. XSD data types describe the parameters and return values.
    • <portType>: Describes all the methods exposed through the Web Service for a specified transfer protocol (such as SOAP, HTTPGet, or SMTP).
    • <operation>: A child of the <portType> element, it specifies which message is the input and which message is the output.
    • <soap:binding>: indicates the transport protocol. It is a child of the <binding> element.
    • <soap:operation>: a grandchild of the <binding> element, it has an attribute "soapAction" that states the SOAPAction HTTP header.

    Description

    A SOAP Test Harness user enters the URL of the WSDL document and then selects the specific Web method that needs to be tested. The user then enters values for the method parameters. Code is generated for

    1. Declaring a proxy class instance and parameter variables,
    2. Instantiating a proxy class object ,
    3. Assigning values to the parameters,
    4. Invoking the Web method, and
    5. Displaying the output.
    The generated output is then sent to either a label or a DataGrid depending on the return type. The user has the opportunity to change the generated code for individual cases. The generated output will be a single ASP.NET file written in C# (See Figure 1 below).

    Components

    Technologies:

    • C#
    • ASP.NET
    • Internet Information Server 5.0 (IIS)
    • .NET Framework SDK
    • Visual Studio.NET (VS.NET)
    The Soap Test Harness is an ASP.NET application consisting of six ASP.NET pages and three C# class definitions. These are:

    1. SoapTestHarness.cs
    2. SoapClientGenerator.cs
    3. ServerFileSystemMaintenance.cs
    4. Home.aspx.cs
    5. EnterParams.aspx.cs
    6. DeclarationCode.aspx.cs
    7. PreProcessCode.aspx.cs
    8. ExecuteCode.aspx.cs
    9. OutputCode.aspx.cs

  • Download complete source code

    The ASP.NET pages are written in C# and implement the "Codebehind" attribute of the "Page" directive.

    Four external items are used to support the application:

    1. WSDL.exe - Creates a Web Service proxy. (Comes with VS.NET.)
    2. CSC.exe - C# command-line compiler. (Comes with VS.NET.)
    3. mkappdir.vbs - IIS script for creating virtual directory. (Comes with IIS 5.0.)
    4. chaccess.vbs - IIS script for changing access permissions. (Comes with IIS 5.0.)

    Figure 1: Page Flow

    Class Definitions

    The parent class is SoapTestHarness (see Figure 2), which has two children -- SoapClientGenerator and ServerFileSystemMaintenance. The SoapTestHarness class stores the namespace, the root directory of the generated client pages, and the locations of the external applications and scripts.

    Figure 2: SoapTestHarness.cs

    
    using System;
    
    namespace imiTestHarness_v2
    {
       public class SoapTestHarness
       {
          public static string HOME_DIRECTORY = "C:\\Inetpub\\wwwroot\\STHClients\\";
          public static string NAMESPACE      = "STHClients";
          public static string WSDL_EXE       = 
    "C:\\Program Files\\Microsoft.Net\\FrameworkSDK\\Bin\\wsdl.exe";
          public static string CSC_EXE        =  "C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.2914\\csc.exe";
          public static string MKAPPDIR_VBS   = "C:\\Inetpub\\AdminScripts\\mkappdir.vbs";
          public static string CHACCESS_VBS   = "C:\\Inetpub\\AdminScripts\\chaccess.vbs";
    
          public SoapTestHarness()
          {
          }
       }
    }
    
    

    The SoapClientGenerator class stores data about the Web Service, retrieves data from the WSDL document, and creates the tags for the client ASP.NET page. A structure made up of three ArrayList objects holds the parameter names, data types, and values. This class uses objects from the System.Xml, System.Xml.XPath, System.Xml.Xsl, and the System.Collections Namespace of the .NET Framework.

    The fillXmlIterator() method (see Figure 3) is a commonly used method by the SOAP Test Harness. It allows the various ASP.NET pages to conveniently retrieve data from the WSDL file. The client passes in the XPath query and the URL of the WSDL document and receives an XPathNodeIterator that it can treat similar to a recordset.

    • The XPathDocument holds the XML data and creates an XPathNavigator that allows us to query the document and compile an XPath query.
    • The XmlNamespaceManager is needed so that we can link element prefixes with a given namespace.
    • The XPathExpression object holds the compiled XPath query, and it is used by the XPathNavigator to carry out the query.
    • The XPathNodeIterator holds the results of the XPath query and allows us to loop through the results.
    Figure 3: fillXmlIterator() method
    
    public XPathNodeIterator fillXmlIterator(string xPathQuery, string xmlUrl)
    {
        try
        {
            XPathDocument       xmlDoc = new XPathDocument(xmlUrl);
            XPathNavigator      xmlNav = xmlDoc.CreateNavigator();
            XmlNamespaceManager nsMgr  = new XmlNamespaceManager(xmlNav.NameTable);
            XPathExpression     xPathExp;
            XPathNodeIterator   iterator;
                
            nsMgr.AddNamespace("ab", "http://schemas.xmlsoap.org/wsdl/");
            nsMgr.AddNamespace("s", "http://www.w3.org/2001/XMLSchema");
            nsMgr.AddNamespace("soap", "http://schemas.xmlsoap.org/wsdl/soap/");
                
            xPathExp = xmlNav.Compile(xPathQuery);
            xPathExp.SetContext(nsMgr);
            iterator = xmlNav.Select(xPathExp);
    
            return iterator;
        }
        catch(Exception ex)
        {
            return null;
        }
    }
    
    
    The ServerFileSystemMaintenance class is needed in order to create directories, generate files, and invoke external applications and scripts. A physical directory and a virtual directory are created that store the generated ASPX file. The virtual directory's Execute Permissions property is updated, allowing users access to the generated ASP.NET page. A proxy file must be created to act as an interface between the generated client and the Web Service so the test harness invokes external applications to create the proxy class and then to compile it.

    In addition, we must create our ASP.NET Web Service client file. We will go over a few methods that demonstrate creating a directory, changing a virtual directory's access permission, and invoking an external application or script.

    The createInstanceDirectory() method (see Figure 4) is called whenever a Web Service client is generated.

    • The System.IO.DirectoryInfo object is used to create the directory. The CreateSubDirectory() method creates the "bin" directory that holds the DLL file from the compiled proxy class.
    • A persistent attribute, "timeStamp", distinguishes one instance from another.
    • HOME_DIRECTORY is a constant attribute declared in the SoapTestHarness class.
    Figure 4: createInstanceDirectory() method
    
    private bool createInstanceDirectory()
    {
       try
       {
          DirectoryInfo baseDir     = new DirectoryInfo(@HOME_DIRECTORY);
          string        instanceDir = this.timeStamp + "\\bin";
          baseDir.CreateSubdirectory(@instanceDir);
          
          return true;
       }
       catch(Exception ex)
       {
          return false;
       }
    }
    
    The updateVirDirectoryAccess() method (see Figure 5) updates an existing virtual directory, allowing the user access to the generated ASP.NET page.
    • Here, the "chaccess.vbs" script bundled with IIS 5.0 is used to modify the access permission.
    • If an exception occurs, a false value is returned and the application acts accordingly.

      Figure 5: updateVirDirectoryAccess() method

      
      private bool updateVirDirectoryAccess()
      {
         try
         {
            string  chaccessArgs = "-a W3svc/1/Root/" + NAMESPACE + "/" + this.getTimeStamp() 
                                   + " " + "+execute";
            runExternalApp(CHACCESS_VBS, chaccessArgs);
      
            return true;
         }
         catch(Exception ex)
         {
            return false;
         }
      }
      
      
      The method runExternalApp(string fileName, string args) (see Figure 6) uses the .NET class System.Diagnostics.Process to invoke external applications. * The name of the script or application file is passed to the FileName property and command-line arguments are passed in to the Arguments property. * "WaitForExit()" will accept an int value instructing the thread to wait n number of milliseconds before it resumes execution. This method is used to ensure the proper synchronization of events.

      Figure 6: runExternalApp(string fileName, string args) method

      
      private bool runExternalApp(string fileName, string args)
      {
         try
         { 
            Process process = new Process();
            process.StartInfo.FileName  = fileName;
            process.StartInfo.Arguments = args;
            process.Start();
            process.WaitForExit(14000);
            process.Dispose();
      
            return true;
         }
         catch(Exception ex)
         {
            return false;
         }
      }
      
      

      ASP.NET Classes

      The Home.aspx file is the entry point to the Soap Test Harness. The user will enter the URL of the WSDL document that VS.NET creates. The methods exposed by the Web Service are listed for the tester to select. Once a method is selected, the user clicks the "Next" link and is forwarded to the parameters page. Home.aspx uses the SoapClientGenerator to retrieve information from the WSDL document and store that data. Let us review one of the methods that use the SoapClientGenerator for retrieving XML data from the WSDL file. The getClassName() method (see Figure 7) uses the fillXmlIterator() method to easily read selected XML nodes from an XML document. An XPath query to retrieve the Web Service name is created and then passed to the fillXmlIterator() method that was discussed earlier. The XPath query accesses the "service" element and selects the "name" attribute. We should recall that the "ab:" prefix was assigned to the "http://schemas.xmlsoap.org/wsdl/" namespace, and the "service" element is defined in that namespace. The "iterator" is treated similarly to a recordset by invoking the MoveNext() method to move through nodes.

      Figure 7: getClassName() method

      
      private string getClassName()
      {
         try
         {
            if(!validateWsdlUrlTextbox())
               return null;
            string className  = null;
            string wsdlUrl    = txtWsdlUrl.Text.Trim();
            string xpathquery = "//ab:service/@name";
      
            XPathNodeIterator iterator = this.scg.fillXmlIterator(xpathquery, wsdlUrl);
            while(iterator.MoveNext())
               className = iterator.Current.Value;
            
            return className;
         }
         catch(Exception ex)
         {
            return null;
         }
      }
      
      
      The EnterParams.aspx page allows the user to enter values for the method parameters, as well as view the returned data type. This page also uses the SoapClientGenerator and the fillXmlIterator() method to get parameter data from the WSDL document. The parameter names, data types, and corresponding text boxes are displayed to the user. The displayParameters() method (see Figure 8) uses Label[] and TextBox[] arrays to hold the WebControls objects as the Soap Harness loops through each to modify their visible property.

      Figure 8: displayParameters() method

      
      protected void displayParameters()
      {
         try
         {
            ArrayList parameters    = (ArrayList) this.ip.parameters;
            ArrayList dataTypes     = (ArrayList) this.ip.dataTypes;
            Label[] dataTypeLabels  = {lblDataType1, lblDataType2, lblDataType3, 
                                       lblDataType4, lblDataType5, lblDataType6,
                                       lblDataType7, lblDataType8, lblDataType9, 
                                       lblDataType10};
            Label[] paramNameLabels = {paramName1, paramName2, paramName3, 
                                       paramName4, paramName5, paramName6,
                                       paramName7, paramName8, paramName9, 
                                       paramName10};
            TextBox[] txtParams     = {txtParam1, txtParam2, txtParam3, 
                                       txtParam4, txtParam5, txtParam6,
                                       txtParam7, txtParam8, txtParam9, 
                                       txtParam10};
      
            if(this.ip.parameters.Count == 0)
            {
               this.lblNoParams.Visible = true;
               this.lblParam.Visible    = false;
               this.lblDataType.Visible = false;
               this.lblValue.Visible    = false;
            }
            else
            {
               for(int i = 0; i < this.ip.parameters.Count; i++)
               {
                  this.lblParam.Visible    = true;
                  this.lblDataType.Visible = true;
                  this.lblValue.Visible    = true;
               
                  if(i == 9)
                  {
                     displayErrorMessage("Only 10 parameters are allowed!");
                     return;
                  }
               
                  dataTypeLabels[i].Visible  = true;
                  dataTypeLabels[i].Text = dataTypes[i].ToString().Replace("s:", "");
                  paramNameLabels[i].Visible = true;
                  paramNameLabels[i].Text = (string) parameters[i];
                  txtParams[i].Visible = true;
               }
            }
         }
         catch(Exception ex)
         {
            displayErrorMessage(ex.Message);
         }
      }
      
      
      The DeclarationCode.aspx, PreProcessCode.aspx, ExecuteCode.aspx, and OutputCode.aspx pages all have the same basic functionality. Each page will invoke a method on the SoapClientGenerator to generate code and then display the code to the user. The user will be able to customize the code and then move on to the next page. The code is stored within the SoapClientGenerator object and that object is passed throughout the application in the Session variable.

      The OutputCode.aspx page uses the ServerFileSystemMaintenance class, which creates the generated ASP.NET page and the corresponding directory, virtual directory, proxy class, and proxy DLL file. The testSoapClient() method (see Figure 9) administers the tasks that create all necessary support files and directories. The ServerFileSystemMaintenance (sfsm) and SoapClientGenerator (scg) objects are used in conjunction with the displayErrorMessage() method. If no exceptions are thrown, then the user is forwarded to the generated ASP.NET page.

      Figure 9: testSoapClient() method

      
      public void testSoapClient()
      {
         try
         {
            if(!this.sfsm.makeDirectory())
            {
               displayErrorMessage("Error creating host directory for testing");
               return;
            }
            
            if(!this.sfsm.makeProxyFile(this.scg.getWsdlUrl()))
            {
               displayErrorMessage("Error creating proxy file");
               return;
            }
      
            this.scg.generateAspxCode();
            if(!this.sfsm.makeAspxFile(this.scg.getAspxCode()))
            {
               displayErrorMessage("Error creating .aspx file");
               return;
            }
      
            string soapClientURL = "http://localhost/STHClients/" + 
                                   this.sfsm.getTimeStamp() + "/" + 
                                   this.sfsm.getTimeStamp() + ".aspx";
            Response.Redirect(soapClientURL, true);
         }
         catch(Exception ex)
         {
            displayErrorMessage(ex.Message);
         }
      }
      
      

      Installation

      To use the Soap Test Harness, a root directory for your generated ASPX files will need to be created. Assign the directory path to the HOME_DIRECTORY attribute in the SoapTestHarness.cs class. The name you give this root directory will be your namespace, therefore you must update the NAMESPACE attribute. The WSDL.exe (proxy generator) and CSC.exe (C# compiler) are part of VS.NET and the .NET framework. The location of these files will need to be assigned to the WSDL_EXE and CSC_EXE attributes, respectively. The default values for these attributes are the default installation locations. Two IIS 5.0 scripts are used to interact with virtual directories -- mkappdir.vbs, and chaccess.vbs. The default values for these attributes are the default installation locations; the values are assigned to the MKAPPDIR_VBS and CHACCESS_VBS.

      ScreenShots

      1. Home.aspx

      2. EnterParams.aspx

      3. DeclarationCode.aspx

      4. PreProcessCode.aspx

      5. ExecuteCode.aspx

      6a. OutputCode.aspx (bool)

      7a. Generated ASP.NET page (bool)

      6b. OutputCode.aspx (DataSet)

      7b. Generated ASP.NET page (DataSet) (Note: Data from SQL Server "pubs" sample database.)

      Pending Issues and Enhancements

      The original plan for interfacing the client with the Web Service was to use the .NET class System.Web.Services.SoapHttpClientProtocol. This is a simple class to use; all we have to do is assign the URL of the Web Service to the "Url" attribute and then call the "invoke()" method, passing in the name of the specific web method as a string. So why was this class not used instead of having to use the WSDL.exe and CSC.exe to create an external proxy? Well, the SoapHttpClientProtocol requires the use of preprocessor attributes that contain literal values of an individual Web method location. Since this program needed to be generic and there is no way to alter the preprocessor attribute at runtime, a workaround needed to be implemented. Note that I could use the SoapMessage class in the System.Runtime.Serialization.Formatters namespace to construct the SOAP envelope, but it uses the "RPC" format instead of the "Document" format that we need. In the future, a System.Xml.XmlTextWriter object will be used to build the SOAP message and a System.Net.WebRequest object will submit the message. This will eliminate the need to dynamically generate temporary proxy classes.

      Summary

      The need to test Web Services for component consumers and developers is a common requirement. The SOAP Test Harness eliminates the needed for developers to write their own testing code. In addition, The SOAP Test Harness facilitates a uniform and generic process for testing Web Services. The Microsoft .NET framework allows developers to rapidly develop applications using XML, XSL, operating systems, and Web Services. The SOAP Test Harness is a testament to how simple and quickly an ASP.NET application can be created using the .NET Framework and Visual Studio.NET.

      About the Author

      Craig Emilio Probus is a consultant for Information Methodologies, Inc. (imi), a leading enterprise Web integrator for higher education. His areas of expertise are Web infrastructure integration and development. He is a Sun-certified programmer for the Java 2 platform, an IBM-certified XML developer, and a graduate of Old Dominion University. Craig Emilio lives in Northern Virginia; he enjoys scuba diving and rooting for the Washington Redskins. He can be reached at probus@itsuccess.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Jul 7, 2005 - Hosting Indigo Web Services
    In the second article of his series on Indigo web services, Chris Peiris explains how to host an Indigo web service and examines the IIS, self hosting, and Windows Activation Service hosting options. He then provides step-by-step instructions and sample code for an IIS-hosted and self-hosted Indigo web service.
    [Read This Article]  [Top]
    Jun 8, 2005 - Indigo Programming Model
    In the first part of his series on Microsoft Indigo, Chris Peiris examines the basics of SOA, explains how Indigo fits into the picture and the problems it solves. He then introduces Indigo's programming model and finishes by building a sample Indigo web service using the Microsoft .Net Framework 2.0.
    [Read This Article]  [Top]
    Nov 10, 2004 - Business Intelligence with Microsoft SQL Server Reporting Services - Part 3
    Adnan Masood concludes his discussion of Microsoft SQL Server Analysis services and Microsoft SQL Server Reporting services. In the final part, he discusses Reporting Server web services and using custom code in reports.
    [Read This Article]  [Top]
    Jul 8, 2004 - Using IE's Web Service Behavior To Create Rich ASP.NET Applications
    This article explains the features of the IE Web service behavior and shows how to asynchronously communicate with an ASP.NET Web service directly from the client.
    [Read This Article]  [Top]
    Jul 6, 2004 - Using .NET and Excel 2003 To Validate E-Mails
    Calvin Luttrell shows how to validate e-mail addresses stored in Excel 2003 and provides a special function for solving that pesky problem Yahoo! mail servers cause.
    [Read This Article]  [Top]
    Jun 9, 2004 - Modifying Web Services Documentation
    This short article describes a quick and easy way to provide some security to an ASP.NET Web service by modifying its associated documentation file.
    [Read This Article]  [Top]
    Jun 2, 2004 - Kerberos Authentication with Web Services Enhancements 2.0
    Kerberos authentication is the cornerstone of Windows operating system authentication architecture. Web Services Enhancement 2.0 (WSE 2.0) extends Kerberos support to ASP.NET Web services. Chris Peiris explains the support for this new feature in WSE 2.0.
    [Read This Article]  [Top]
    Dec 15, 2003 - Realizing a Service-Oriented Architecture with .NET
    Chip Irek examines the architectural issues and component design issues of building a .NET application in a service-oriented architecture.
    [Read This Article]  [Top]
    Nov 24, 2003 - Consuming Asynchronous Web Services
    Thiru Thangarathinam shows how to use asynchronous Web services, Windows Service applications, server-based timer components and .NET XML API classes to create high-performance, scalable, and flexible applications.
    [Read This Article]  [Top]
    Nov 12, 2003 - Implementing Paging and XSLT Extensions Using XSLT in .NET - Part 2
    Part one showed how to transform XML data into HTML by using an XSL stylesheet from within a .NET application. This part explains how to make use of XSLT Extension objects and invoke a C# class method from an XSL stylesheet.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers