How to use Wortschatz Leipzig web services in C#

C# Sourcecode IconIn that article I provided a small C# based library that allows you to easily access the thesaurus web service of the Wortschatz Leipzig project.

Now, in this article, I want to describe briefly what “obstacles” I had to overcome to address the web service from C#. Despite the fact that the Wortschatz Leipzig team provides a WSDL file for their web service, it is not done with adding a Web- or ServiceReference in Visual Studio.

 

Add Wortschatz Leipzig web service to Visual Studio solution

First you need to create a ServiceReference to the desired web service. For this article, let’s take the thesaurus web service. The path to the WSDL file, which is required to create the ServiceReference, is:

http://wortschatz.uni-leipzig.de/axis/services/Thesaurus?wsdl

Info: I called the ServiceReference “ThesaurusClient”.

Now one would think that everything is done and you would have to instantiate the client class and simply call the execute()-function provided by the web service. Far from it!

Creating the Client

Now we need to instantiate and configure the web service client. The Wortschatz Leipzig web service requires credentials for access.

ThesaurusClient service = new ThesaurusClient();
service.ClientCredentials.UserName.UserName = "anonymous";
service.ClientCredentials.UserName.Password = "anonymous";

Create call parameters

In the next step, the call parameters need to be created. The execute()-function of the web service takes 3 parameters – the word for which synonyms should be provided, the maximum number (“Limit”) of synonyms and the dictionary (“corpus”), in which the synonyms are to be searched. Unfortunately you can not pass this parameters as string, int, string, but must hand it in a special data structure.

DataMatrix matrix = new DataMatrix();
List<DataVector> vector = new List<DataVector>();
DataVector dv = new DataVector();
dv.Add("Wort");
dv.Add("Kindergarten");
vector.Add(dv);
dv = new DataVector();
dv.Add("Limit");
dv.Add(100);
vector.Add(dv);
matrix.AddRange(vector);

RequestParameter request = new RequestParameter();
request.corpus = "de";
request.parameters = matrix;

The above code gives a maximum of 100 synonyms for the word “Kindergarten” and searches for them in the dictionary “de” (for (DE)utschland/germany).

Calling the web service

Now we have to actually query the web service. But even here was a “hidden difficulty”. Thus the credentials (“anonymous: anonymous”) will be passed in the right way, the execute()-function has to be called in a OperationContextScope and the headers of the request have to be manually manipulated before calling the webservice.

using (OperationContextScope scope = new OperationContextScope(service.InnerChannel))
{
   var httpRequestProperty = new HttpRequestMessageProperty();
   httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(service.ClientCredentials.UserName.UserName + ":" + service.ClientCredentials.UserName.Password));
   OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;

   ResponseParameter resp = service.execute(request);
}

Evaluating the response data (aka getting the synonyms)

Also, when reading data, there were problems. While the request was working at this point, the result could not be parsed correctly. So the data structure that was supposed to contain the response from the web service was empty.

At this point I have applied a Quick’n’Dirty solution with help of a regular expression. First, however, we need the raw XML, befor we can get the synonyms out of it. To get to this, we need a MessageInspector for our web service client.

Therefore we have to add the following two classes to our code:

private class InspectorBehavior : IEndpointBehavior
{
   public string LastRequestXML
   {
      get
      {
         return myMessageInspector.LastRequestXML;
      }
   }

   public string LastResponseXML
   {
      get
      {
         return myMessageInspector.LastResponseXML;
      }
   }

   private MyMessageInspector myMessageInspector = new MyMessageInspector();
   public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
   {
   }

   public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
   {
   }

   public void Validate(ServiceEndpoint endpoint)
   {
   }

   public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
   {
      clientRuntime.MessageInspectors.Add(myMessageInspector);
   }
}

private class MyMessageInspector : IClientMessageInspector
{
   public string LastRequestXML { get; private set; }
   public string LastResponseXML { get; private set; }

   public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
   {
      LastResponseXML = reply.ToString();
   }

   public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
   {
      LastRequestXML = request.ToString();
      return request;
   }
}

Now we need to enable the Inspector. This should be done right after instantiating our ThesaurusClient.

ThesaurusClient service = new ThesaurusClient();
var requestInterceptor = new InspectorBehavior();
service.Endpoint.Behaviors.Add(requestInterceptor);

Then we can get access to the XML data that we have received from the Wortschatz Leipzig web service after calling the execute()-function.

ResponseParameter resp = service.execute(request);
string requestXML = requestInterceptor.LastRequestXML;
string responseXML = requestInterceptor.LastResponseXML;

In the next step we have the response of the Wortschatz Leipzig web service as an XML string. So we can parse the synonyms with a small regular expression and put it in a list.

Regex reg = new Regex("<ns\d+:dataRow>(.*?)</ns\d+:dataRow>");
MatchCollection mc = reg.Matches(responseXML);

List<string> synonymList = new List<string>();

if (mc.Count > 0)
   synonymList.AddRange((from Match m in mc select m.Groups[1].Value));

All synonyms which were returned by the web service can be found in the list “synonymList”.

Conclusion & Download

That’s it. I hope I could help one or the other of you. Who wants to get the whole source code can download it from that article or get it from GitHub.

Leave a comment

Please be polite. We appreciate that. Your email address will not be published and required fields are marked