[
Advertise | Submit Code | About us | Contact us | Link us
]
Go!
Membership Services
Login
Register

Home
C# General

General

C# Language

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting
C# Windows Forms

General

Combo and List boxes

Miscellaneous Controls

Button Controls

Edit Controls
Cutting Edge

ASP.NET 2.0

Visual Studio 2005

Windows Longhorn

SQL Server 2005
C# Multimedia and GDI+

General

DirectX

GDI+

Audio
Internet & Web

General

Images and multimedia

Database

Utilities

Security

ASP.NET Controls

Design and Architecture

Webservices
.NET

General

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting

ADO.NET

XML.NET

Tools

Enterprise

IDE
Visual Basic .NET

VB.NET General

VB.NET Controls
General Reading

.NET Books Review

Product Showcase

Book Chapters

Business Design & Strategy
Community

Discuss

Job Board

Discussion

CodeXchange
DeveloperLand

Advertise

Submit Code

About us

Contact us

Link us
Miscellaneous

Favorite Links

Downloads

Programming Sites

Top Stories
Regular Expressions

E-Mail

Date/Time
Home > Internet & Web > Webservices
Web Services between .NET, Java and MS SOAP Toolkit - Part II
Posted by on Monday, August 23, 2004 (EST)

This second article in this series dedicated to Web services comes as a sequel to the first one in which I started to tell you how you could build different kind of clients and services using MS SOAP Toolkit, Apache SOAP for Java and .NET.

This article has been viewed: 2,624 times
Technology: Webservices.

This second article in this series dedicated to Web services comes as a sequel to the first one in which I started to tell you how you could build different kind of clients and services using MS SOAP Toolkit, Apache SOAP for Java and .NET Framework.

In the last article I mentioned something about the incompatibility between a MS SOAP client and an Apache SOAP server (the infamous xsi:type). As far as I know the version 2.2 didn't solve this problem, which is Apache SOAP Server is still expecting all parameters to have a type specified. But, the good news is that there is a work around to this problem. Many of you sent me e-mails asking how to do this. Well it is fairly simply.

Apache SOAP Server and clients

Do you remember the Apache SOAP server we wrote last time? Well another good news is that you don't have to change anything inside the server. You only need to change the deployment descriptor.

Let me tell you more about the workaround before writing anything. The major difference between MS implementation of SOAP and Apache for Java's is that the former relies on WSDL files to fully describe the service when the latter doesn't. This is why in the initial implementation of the Apache SOAP for Java the type is required to be specified for each parameter. The server has no other mean to know the type of the parameters unless is specified in the call. In the MS implementation the WSDL file has enough information and the server can figure out even if the call tells nothing about this.

Now, the solution to our problem is: when you deploy your service you can specify the type mapping of each parameter in your methods. The Java service uses this whenever there isn't enough information in the method call.

So you must add a mappings section to your deployment script. I modified the deployment descriptor for our service.

<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment"
id="urn:MyService ">

<isd:mappings>
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
             xmlns:x="" qname="x:num1"
             xml2JavaClassName="org.apache.soap.encoding.soapenc.DoubleDeserializer"/>   
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="" qname="x:num2"            xml2JavaClassName="org.apache.soap.encoding.soapenc.DoubleDeserializer"/>
</isd:mappings>

</isd:service>
 

That's all. Believe it or not that's all you have to change. The MS STK client doesn't need any change either. The same mention for the .NET client, don't change anything.

This will complete our incursion to building clients and services (simple ones) using the three major frameworks available. I must mention here that there are other frameworks for building SOAP servers and clients so don't be shy and publish source code and information so we can all learn about them. I remember seeing among people on SOAP Builders discussion group another name: Glue. They were at beta version last time a checked their web site but I'm sure they will quickly be releasing their product.

Generic client for Web Services

Ok so now we know hot to build a web service when we have enough information about the service itself: we are either the developers of the service or good friends with the developer, so we can get the “signature” of the service at the time we write the client.

Now, suppose you want to build a client that is able to call a service knowing only the name of the methods or something similar. My example will try to add two numbers searching a Math service and calling the methods. A more practical example could be a stock checker or something similar.

The steps I follow are:
- search the UDDI and find businesses which can help me solve my problem. The way we find the business is not standardized since there isn't a set of categories with businesses. For example we'll make the convention that Math businesses will be stored under Math category. Next we'll query for the URL where the web service stores the WSDL file.
This is the first step to finalize our solution. I'll skip the code for this section since UDDI and related APIs are the subject of a future article.
- Once we have the WSDL file we'll parse this file and find out information about the web service. Based on this information we'll build a SOAP request. To build a soap request I used the low level API in STK since we don't know from the beginning how many parameters the service will call.

And here is the code:

Option Explicit

Function BuildOperation( _
    ByVal WSDLFileName As String, _
    ByVal WSMLFileName As String, _
    sOperation As String) As CWSDLOperation

    Dim Reader As WSDLReader
    Dim EnumService As EnumWSDLService
    Dim Service As WSDLService
    Dim EnumPort As EnumWSDLPorts
    Dim Port As WSDLPort
    Dim EnumOperation As EnumWSDLOperations
    Dim Operation As WSDLOperation
    Dim EnumMapper As EnumSoapMappers
    Dim Mapper As SoapMapper
    Dim Fetched As Long
    
    Dim objWSDLOperation As CWSDLOperation
    Dim objOperationPart As COperationPart
    Dim bAddParts As Boolean
    
    Set objWSDLOperation = New CWSDLOperation
    
    Set Reader = New WSDLReader
    Reader.Load WSDLFileName, WSMLFileName
    
    Reader.GetSoapServices EnumService
    
    EnumService.Next 1, Service, Fetched
    Do While Fetched = 1
        
        Service.GetSoapPorts EnumPort
        
        EnumPort.Next 1, Port, Fetched
        Do While Fetched = 1
        
            Port.GetSoapOperations EnumOperation
            
            EnumOperation.Next 1, Operation, Fetched
            Do While Fetched = 1
            
                
                //check to see if the operation is here
                bAddParts = False
                If InStr(1, Operation.soapAction, "." + sOperation) > 0 Then
                    With objWSDLOperation
                        Set .m_Parts = New Collection
                        .m_PortAddress = Port.address
                        .m_SoapAction = Operation.soapAction
                    End With
                    bAddParts = True
                
                    Operation.GetOperationParts EnumMapper
                    
                    EnumMapper.Next 1, Mapper, Fetched
                    Do While Fetched = 1
                    
                        If bAddParts Then
                            Set objOperationPart = New COperationPart
                            objOperationPart.m_Name = Mapper.partName
                            Call objWSDLOperation.m_Parts.Add(objOperationPart)
                        End If
                        
                        EnumMapper.Next 1, Mapper, Fetched
                    Loop
                
                End If
                
                EnumOperation.Next 1, Operation, Fetched
            Loop
            
            EnumPort.Next 1, Port, Fetched
        Loop
        
        EnumService.Next 1, Service, Fetched
    Loop
    Set BuildOperation = objWSDLOperation

End Function

Function build BuildOperation() parses the WSDL file and gathers information about the service: name, parameters, namespaces used, etc and finally returns a CWSDLOperation object.

With this information we can move next to build the SOAP request and invoke the web service. The service is invoked by calling Execute method on CWSDLOperation object. In my example the Execute method will simply print the result of the add operation.

In my example the rule I applied for finding the right method and passing the parameter is pretty simple but in a real application you can implement more sophisticated mechanisms or assume there are few patterns for each method naming.

Here is the code for the CWSDLOperation class.

Option Explicit

Private Const WRAPPER_ELEMENT_NAMESPACE = ""

Public m_PortAddress As String
Public m_SoapAction As String
Public m_Parts As Collection

Public Sub Execute()
    If m_SoapAction <> vbNullString Then
        On Error GoTo ErrorHandler
        
        Dim Serializer As SoapSerializer
        Dim Reader As SoapReader
        Dim Connector As SoapConnector
        
        Dim part As COperationPart
        Dim sMethod As String, sNamespace As String
        
        Set Connector = New HttpConnector
        Connector.Property("EndPointURL") = m_PortAddress        
        Connector.Property("SoapAction") = m_SoapAction
        Connector.BeginMessage
        
        Set Serializer = New SoapSerializer
        Serializer.Init Connector.InputStream
        
        sMethod = Mid$(m_SoapAction, InStrRev(m_SoapAction, ".") + 1)
        sNamespace = Left$(m_SoapAction, InStr(m_SoapAction, "/action") - 1)
        
        Serializer.startEnvelope
        Serializer.startBody
        Serializer.startElement sMethod, sNamespace + "/message/", , "m"
        
        For Each part In m_Parts
            Serializer.startElement part.m_Name
            Serializer.writeString "20"
            Serializer.endElement
        Next
        
        Serializer.endElement
        Serializer.endBody
        Serializer.endEnvelope
        
        Connector.EndMessage
        
        Set Reader = New SoapReader
        Reader.Load Connector.OutputStream
        
        If Not Reader.Fault Is Nothing Then
            MsgBox Reader.faultstring.Text, vbExclamation
        Else
            Debug.Print Reader.RPCResult.Text
        End If
    End If
    
    Exit Sub

ErrorHandler:
    MsgBox "ERROR: " & Err.Description, vbExclamation
    Err.Clear
    Exit Sub
End Sub
COperationPart class is very simply:
Option Explicit

Public m_Name As String
If you want to simplify the code you can substitute the COperationPart class with a String variable. There are more fields that can be added to the COperationPart class but I removed them for simplicity of the code. The other information available in the WSDL file for a OperationPart are:

- elementName
- callIndex
- elementType
- messageName
- isInput
- partName
- xmlNameSpace
- comValue
- parameterOrder

To test the sample application you need to build 2 simple Web services with STK MathLib1 and MathLib2. MathLib1 implements add method and MathLib2 implements addNumbers method. Both methods accept 2 parameters as double values.

After you create these two web services change the namespace in one of them so something else than default, so you replicate a real situation.

Create a VB project, add the two classes, than add a form, on the form add a button and insert the following code in his click event.

Private Sub cmdCallServices_Click()
    Call BuildOperation("C:\work\xarea\soap\MathLib\MathLib1\MathLib1.WSDL", _
        "C:\work\soap\MathLib\MathLib1\MathLib1.WSML", "add").Execute
    Call BuildOperation("C:\work\xarea\soap\MathLib\MathLib2\MathLib2.WSDL", _
        "C:\work\soap\MathLib\MathLib2\MathLib2.WSML", "add").Execute
End Sub

Compile and you are ready to go!

I hope this article will help better understand web services and SOAP.

Top Go to Table of Contents

About Catalin Tomescu

I'm a software engineer working for a company in US. My interests are developeing application with .NET Framework, Web Services, web applications, distributed applications and database driven applicat

Click here if you want to know more about .

Other articles that may interest you

  • Write a Word Add-In – Part 0
  • Write a Word Add-In – Part I
  • Lengthy Operations on Single Thread in .NET Application
  • Learning Draughts
  • Exceptions and Performance
  • Average Rating :

    Discussion Forums
    Got a programming related question? Hopefully someone has the answer... Want to help out other developers? Visit our discussion forums.

    Sponsored by:

    New Articles

  • Exceptions and Performance
    Almost every time exceptions are mentioned in mailing lists and newsgroups, people say they're really expensive.Let's examine that claim, shall we?

  • Creating multilingual websites - Part 1
    Extend the existing globalization capabilities of .NET to create flexible and powerful multilingual web sites. First, create a custom ResourceManager, and then create custom localized-capable server controls to easily deploy multilingual functionality.

  • Parameter passing in C#
    Many people have become fairly confused about how parameters are passed in C#, particularly with regard to reference types. This page should help to clear up some of that confusion

  • Most Popular Articles

  • LDAP, IIS and WinNT Directory Services
    This article explains how to use .NET Directory Services to retrieve and search directory objects, create new directory objects and edit or delete existing directory objects. Describes Active Directory Application Mode (ADAM) and how to use the IIS, WinNT and LDAP directory (ADSI) provider.

  • An in-depth look at WMI and instrumentation, Part II
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article is the second part of a two-part series.

  • An in-depth look at WMI and instrumentation, Part I
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article provides an in-depth look at WMI and MOM 2005

  • New Books

  • Murach's ASP.NET 2.0 Upgrader's Guide: VB Edition
    What’s new and how to use it! That’s what this book delivers if you’re a VB developer who’s interested in upgrading from ASP.NET 1.x to ASP.NET 2.0.

  • C# in easy steps
    Learn to program with Microsoft’s premier programming language. No previous programming knowledge is assumed. With numerous easy-to-follow examples, this title explains the essentials of object-oriented programming with C#.

  • Murach's ASP.NET web programming with VB.NET
    Murach's ASP.NET web programming with VB.NET by Doug Lowe and Anne Prince is a in depth training and reference book for ASP.NET programming using VB.NET. The book builds upon Murach's previous books and covers more advanced concepts for programming ASP.NET pages.

  • Got Code?

    if you have any article , source code , or anything else you'd like to share with this community that you think others might find useful, please submit it here and we will gladly make it available on this site. submit@developerland.com.
    Partners

    All articles are copyrighted by their individual authors unless otherwise specified , everything else Copyright ©2004-2006 DeveloperLand