A C# SOAP Apache Client

Introduction

First of all, let me tell you that I am not a C# expert. I am primarily a Java developer but have been experimenting C# and the .NET platform. Basically I am developing a SOAP Web Service using Java and Apache SOAP, and have decided to give my clients an option when and how they access the service. Hence I am going to provide a Web/JSP user interface and a native Windows application written in C#. My main motivation for writing this article is that fact that I could not find anything else like it on the web. There were plenty of articles telling me how I can use the Apache SOAP API to use a .NETTM service, but not the other way round.
We'll start with a refresher on some of the terminology I will be using:

  • SOAP:- Simple Object Access Protocol (SOAP) is a way for a program running in one kind of operating system (such as Windows 2000) to communicate with a program in the same or another kind of an operating system (such as Linux) by using the World Wide Web's Hypertext Transfer Protocol (HTTP)and its Extensible Markup Language (XML) as the mechanisms for information exchange.

  • Apache SOAP:- The Apache Foundations implementation of the SOAP protocol written in Java.

  • C#:- C# (pronounced "C-sharp") is a new object-oriented programming language from Microsoft, which aims to combine the computing power of C++ with the programming ease of Visual Basic. C# is based on C++ and contains features similar to those of Java.

Please note that this document does not covering installing Apache Tomcat, Apache SOAP or the .NETTM SDK. See the resources section for more information and links to all these projects.

Summary

In order to make use of a Apache SOAP web service using C# you need to do the following steps:

  1. Create a proxy class that implements all the methods you want to be able to call from your client. This class needs to extend the System.Web.Services.Protocols.SoapHttpClientProtocol.

  2. The constructor of this class needs to set the URL property of the above class. Basically this will be the URL of the Apache SOAP rpcrouter servlet e.g. http://localhost:8080/apache-soap/servlet/rpcrouter

  3. The proxy class needs to have a WebServiceBindingAttribute set. This defines the name of the web service and the namespace that the service is to use. The Name is usually the ID of the Apache SOAP Service. The namespace is usually the URL of the server hosting the service.

  4. You will need to define a method in the proxy for each method that the service supports and the client wants to use. This method will need to match the signature of the method in the web service itself i.e. if your service defines a method called deleteItem which takes a string as an argument, you will need to define a method in the proxy class called deleteItem(string id).

  5. Each method will need to have an associated SoapDocumentMethodAttribute, this defines the SOAPAction, as well as the name of the Apache SOAP Service that you are connecting to. It also defines the XML encoding style and how the parameters are formatted in the body of the SOAP request.

  6. Each method will then make use of the Invoke method provided by the SoapHttpClientProtocol class to actually call the method on the web service and get the result.

  7. Your client class will then simply need to create an instance of the proxy you have just created, and make calls on the method that it implements, the proxy handles sending the requests to the Apache SOAP server and retrieving the results.

Details

Ok let's get down to business, the above list gave you a brief overview of the process, I am now going to expand on it and show you the code that I used to talk to my service.

The Service

I'll start by giving you the code to my Apache SOAP service:

package com.konnect.soap;
public class HelloService
{
public String hello(String name)
{
return "Hello "+name+" pleased to meet you";
}
}

That's it, now all you have to do it compile the class, and place it in a location that Apache SOAP can load it from, and then deploy it using the Apache SOAP admin tool. In this example I have given the service an ID of "urn:HelloService".

The C# Proxy Class

Since I wrote the service I know the exact signature of all the methods in my service. So my proxy class only needs to implement 1 method. The code is below:

namespace HelloService
{
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services;
using System.Web.Services.Protocols;
[System.Web.Services.WebServiceBindingAttribute(Name="urn:ItemManager",Namespace=
http://localhost:8070/apache-soap/servlet/rpcrouter)]
public class HelloProxy: System.Web.Services.Protocols.SoapHttpClientProtocol
{
public HelloProxy()
{
//You will need to adjust this Url to reflect the location of your service.
this.Url = http://localhost:8080/apache-soap/servlet/rpcrouter;
}
/* The following attribute tells the Soap client how to
* encode the data it sends to the Url as well as which
* service on the server the request is for.
*
* Don't worry all is explain later in the article
*/
[System.Web.Services.Protocols.SoapDocumentMethodAttribute
("",RequestNamespace="urn:HelloService",ResponseNamespace="urn:HelloService",Use=
System.Web.Services.Description.SoapBindingUse.Encoded, ParameterStyle=
System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string hello(string name)
{
/* Call the Invoke method with the method
* name, and its arguments as an array of objects.*/
object [] results = this.Invoke("hello",new object[] { name });
/* we know that the result is a string, so we can
* safely cast it to the correct type
* we also know we are only expecting a singe object
* to be returned so only return the 1st element
*/
return ((string)(results[0]));
}
}
}
//End of HelloService Namespace

Looks pretty simple doesn't it. The only thing that really needs to be explained are the sections of the code in '[' brackets. Basically these are attributes associated with the method/class that provide extra information about the method/class.
The WebServiceBindingAttribute declares that methods within this class will bind to a XML service. The methods that bind to an XML service need to define how they intend to send and receive SOAP messages, this is done via the SoapDocumentMethodAttribute. This attribute specifies the SOAPAction(nothing in our case), the request and response namespaces. When it comes to Apache SOAP these namespaces actually define the service ID that all calls should be directed to. The final 2 parameters define how parameters to the method are to be encoded, and how they should be formatted in the body section of the SOAP envelope.

There are 2 main types of encoding Literal, and Encoded, Literal encoding does not provide any extra hints as to the type of the parameter being sent across the wire. Encoded however does provide this extra information. In order for you to interact with Apache SOAP services you will need to ensure that you always use Encoded parameters. This is because Apache SOAP does not try to guess what a parameter is, it would rather be told what it is. There are 2 format options, wrapped and bare. Wrapped seems to give me the most success when working with Apache SOAP services, Apache SOAP complains and throws and exception when Bare parameters are sent across.

We need to complile this class as a library(DLL), and then reference it when we compile our client. This is done using the following command:

csc /t:library HelloService.cs

This should give us a HelloService.dll file in our current directory.

The Client

The final step. The listing for the client is below:

namespace HelloService
{
public class HelloClient
{
public static void Main(String [] args)
{
HelloService service =
new HelloService();
Console.WriteLine(service.hello("Robert"));
}
}
}
//End of the HelloService namespace

All we have to do now is compile the above class. This is done using the command:
csc HelloClient.cs /r:HelloService.dll

We should now have a HelloClient executable in our current directory. Now if we start Tomcat with Apache SOAP installed, and ensure we have deployed our service. We should be able to run our client and get a response from the server that looks like this:

Hello Robert pleased to meet you.

If you are interested in seeing what is being sent across the wire, you can make use of the TcpTunnelGui that comes with the Apache SOAP package. This allows you to dump all traffic sent to a specific port, and then forward it on to the real location.

In order to see what is going on, adjust the Url parameter you specified in the HelloService C# class have a port of 8070. Then start the TcpTunnelGui using the following command:

java -jar <path to soap.jar> org.apache.soap.util.net.TcpTunnelGui 8070 localhost 8080

This assumes that Tomcat is running on your local machine on port 8080, and that you want the tunnel to listen on port 8070. If you run the client again you should see the SOAP request being sent, and the associated responses from the Apache SOAP server. 

Resources

Apache Tomcat
:-
http://jakarta.apache.org/tomcat/
Apache-SOAP:-
http://xml.apache.org/soap/
.NETTM SDK:- http://msdn.microsoft.com
The C# Corner:-
http://www.c-sharpcorner.com


Similar Articles