| NetworkedPlanet | TMCore Web Services Guide |
All of the HTTP web services can be invoked using an HTTP POST with the POST request body containing a request XML as described in the section above. The request document should be POSTed to the .aspx page that implements the operation. The requester should check the status and content of the HTTP response received. A 200 OK status code indicates that the request was successfully processed.
Example 2. Calling HTTP Web Services From C#
The listing below shows an example of invoking a web serivce
over HTTP from within a C# program. Note that the GetResponse()
method has been written to be generic and can be used to access any
of the NetworkedPlanet web service operations. A complete working
program based on this example code can be found in the
examples/CS directory of your
installation.
private void ProcessRequest(string serviceApplicationUrl, string topicmapName, string searchString)
{
// First construct the URL. We start with the path to the application
// directory provided by the user. Expand this by adding the operation
// ASPX page address (with a slash separator if needed).
string requestUrl = serviceApplicationUrl;
if (!requestUrl.EndsWith("/"))
{
requestUrl += "/";
}
requestUrl += "GetTopicsByName.aspx";
Hashtable parameters = new Hashtable();
parameters["topicmap"] = topicmapName;
parameters["name"] = searchString;
XmlDocument responseDoc = new XmlDocument();
try
{
HttpStatusCode statusCode = GetResponse(requestUrl, parameters, responseDoc);
if (statusCode == HttpStatusCode.OK)
{
System.Console.WriteLine("Search request was processed successfully. Results follow.");
}
else
{
System.Console.WriteLine("Search request failed: " + statusCode.ToString() + ". Details follow.");
}
XmlTextWriter writer = new XmlTextWriter(System.Console.Out);
writer.Formatting = Formatting.Indented;
responseDoc.WriteTo(writer);
}
catch (System.Net.WebException webex)
{
System.Console.Error.WriteLine("Error encountered in sending request. Please check the service application URL and try again.");
System.Console.Error.WriteLine(" Error detail: " + webex.Message);
}
}
/// <summary>
/// Attempts to contact a NetworkedPlanet webservice, passing in the specified parameters.
/// </summary>
/// <param name="requestUrl">The URL of the service to contact</param>
/// <param name="parameters">The parameters to pass to the service.</param>
/// <param name="responseDoc">The response XML received from the web service</param>
/// <returns>The HTTP status code of the response</returns>
/// <exception cref="System.Net.WebException">Raised if the service could not be reached.</exception>
/// <remarks>The <c>parameters</c> hashtable must use string keys and the value for each key must be either
/// a string or an IList of string.</remarks>
private HttpStatusCode GetResponse(string requestUrl, Hashtable parameters, XmlDocument responseDoc)
{
// Construct the request XML
XmlDocument requestDoc = new XmlDocument();
XmlElement requestEl = requestDoc.CreateElement("request");
requestDoc.AppendChild(requestEl);
// Parameters should be either strings or lists of strings
foreach(string key in parameters.Keys)
{
if (parameters[key] is string)
{
XmlElement param = requestDoc.CreateElement("param");
param.SetAttribute("name", key);
param.InnerXml = parameters[key] as string;
requestEl.AppendChild(param);
}
else if (parameters[key] is IList)
{
// If the parameter is a list of strings, write a separate
// param element for each item in the list.
foreach(string item in (parameters[key] as IList))
{
XmlElement param = requestDoc.CreateElement("param");
param.SetAttribute("name", "key");
param.InnerXml = item;
requestEl.AppendChild(param);
}
}
}
// Perform an ASCII encoding of the request xml
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] encodedBody = encoding.GetBytes(requestDoc.OuterXml);
// Construct the request object
HttpWebRequest webRequest = HttpWebRequest.Create(requestUrl) as HttpWebRequest;
webRequest.ContentType = "text/xml";
webRequest.ContentLength = encodedBody.Length;
webRequest.Method = "POST";
Stream bodyStream = webRequest.GetRequestStream();
bodyStream.Write(encodedBody, 0, encodedBody.Length);
bodyStream.Close();
HttpWebResponse webResponse = null;
try
{
webResponse = webRequest.GetResponse() as HttpWebResponse;
}
catch (System.Net.WebException webEx)
{
webResponse = webEx.Response as HttpWebResponse;
}
// NOTE: this will throw an exception out to the caller if the
// response is not an XML document.
responseDoc.Load(webResponse.GetResponseStream());
return webResponse.StatusCode;
}Example 3. Calling HTTP Web Services From VB.NET
' Contains the logic for issuing a search request and processing
' the results.
Sub DoRequest(ByVal serviceUrl As String, ByVal topicmapName As String, ByVal searchString As String)
Dim requestUrl As String
requestUrl = serviceUrl
If Not (requestUrl.EndsWith("/")) Then
requestUrl = requestUrl + "/"
End If
requestUrl = requestUrl + "GetTopicsByName.aspx"
System.Console.WriteLine(requestUrl)
Dim params As New Hashtable
params("topicmap") = topicmapName
params("name") = searchString
Dim responseDoc As New Xml.XmlDocument
Dim responseCode As HttpStatusCode
Try
responseCode = GetResponse(requestUrl, params, responseDoc)
If (responseCode.Equals(HttpStatusCode.OK)) Then
System.Console.WriteLine("Search process successfully. Results follow:")
Else
System.Console.WriteLine("Search request failed. Error details follow:")
End If
Dim writer As XmlTextWriter
writer = New XmlTextWriter(System.Console.Out)
writer.Formatting = Formatting.Indented
responseDoc.WriteTo(writer)
Catch ex As WebException
System.Console.Error.WriteLine("Error processing request: " + ex.Message)
System.Console.Error.WriteLine(" Please check the service URL and try again.")
End Try
End Sub
' Performs the "heavy lifing" of the application. This function posts
' a set of parameters (defined in the params Hashtable) to the
' URL specified by requestUrl and parses the response into
' responseDoc. Because all of the NetworkedPlanet web service
' operations use the same request format, this method can
' be reused to invoke any of the operations we support.
' The keys in the params Hashtable must be strings and the
' values must be either strings or ILists of strings.
Function GetResponse(ByVal requestUrl As String, ByVal params As Hashtable, ByVal responseDoc As XmlDocument) As HttpStatusCode
Dim requestDoc As XmlDocument
Dim requestEl As XmlElement
Dim paramEl As XmlElement
Dim key As String
requestDoc = New XmlDocument
requestEl = requestDoc.CreateElement("request")
requestDoc.AppendChild(requestEl)
For Each key In params.Keys
If (TypeOf params(key) Is IList) Then
' Extract each item in the list in turn add add
' a separate param element for it
Dim paramValue As String
For Each paramValue In params(key)
paramEl = requestDoc.CreateElement("param")
paramEl.SetAttribute("name", key)
paramEl.InnerXml = paramValue
requestEl.AppendChild(paramEl)
Next
Else
' Create a single param element for the item value
paramEl = requestDoc.CreateElement("param")
paramEl.SetAttribute("name", key)
paramEl.InnerXml = params(key)
requestEl.AppendChild(paramEl)
End If
Next
System.Console.WriteLine(requestDoc.OuterXml)
Dim encodedBody As Byte()
Dim asciiEncoding As New ASCIIEncoding
encodedBody = asciiEncoding.GetBytes(requestDoc.OuterXml)
Dim httpRequest As HttpWebRequest
httpRequest = HttpWebRequest.Create(requestUrl)
httpRequest.Method = "POST"
httpRequest.ContentLength = encodedBody.Length
httpRequest.ContentType = "text/xml"
Dim requestStream As Stream
requestStream = httpRequest.GetRequestStream()
requestStream.Write(encodedBody, 0, encodedBody.Length)
requestStream.Close()
Dim httpResponse As HttpWebResponse
Try
httpResponse = httpRequest.GetResponse()
Catch ex As WebException
httpResponse = ex.Response
End Try
If httpResponse.ContentType = "text/xml" Then
Dim reader As New XmlTextReader(httpResponse.GetResponseStream())
responseDoc.Load(reader)
Else
' We shouldn't get non XML content return from NetworkedPlanet
' requests, but this handles the case that the server returns s
' some default error page (e.g. if access is denied) by embedding
' the response text inside a wrapper element
responseDoc.AppendChild(responseDoc.CreateElement("NonXmlResponse"))
Dim rdr As New StreamReader(httpResponse.GetResponseStream())
responseDoc.InnerText = rdr.ReadToEnd()
rdr.Close()
End If
Return httpResponse.StatusCode
End Function
Example 4. Calling HTTP Web Services From Javascript
The following example shows the use of the XmlHttpRequest object provided by some browsers. There are a number of cross-browser libraries that help you avoid browser issues in using Javascript.
/**
* Construct and post the request and handle the response
*/
function DoSearch()
{
// Assumes that our page has three text fields for providing the request parameters
oServiceUrl = document.getElementById("serviceUrl")
oTopicmap = document.getElementById("topicmap")
oSearchString = document.getElementById("searchString")
// A placeholder element on our page for progress / result messages
oMessage = document.getElementById("message");
szRequestUrl = oServiceUrl.value
if (szRequestUrl.charAt(szRequestUrl.length - 1) != "/") {
szRequestUrl = szRequestUrl + "/"
}
szRequestUrl = szRequestUrl + "GetTopicsByName.aspx"
szRequestBody = "<request><param name='topicmap'>" + oTopicmap.value +
"</param><param name='name'>" + oSearchString.value + "</param></request>"
oMessage.innerText = "Sending request. Please wait...";
oMessage.className = "pending";
DoPost(szRequestUrl, szRequestBody);
}
/**
* Posts the specified content to the specified URL using
* the global asynchronous request object 'req'. When the
* request status changes, the ProcessRequestChange function
* will be invoked
*/
function DoPost(url, content)
{
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = ProcessRequestChange;
req.open("POST", url, true);
req.send(content);
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = ProcessRequestChange;
req.open("POST", url, true);
req.send(content);
}
}
}
function ProcessRequestChange()
{
if (req.readyState == 4) {
if (req.status == 200) {
// Handle successful response.
// Response XML can be found in req.responseXML
} else {
// Handle error reponse.
// Error XML document can be found in req.responseXML
}
}
}Although the HTTP interface also accepts HTTP GET requests, these are restricted by the limitations imposed on URL lenght and URL parameter structures. We therefore recommend that you always use POST requests for consistency.
The SOAP service implementation endpoints are provided by the .asmx files contained in the service web applications. This is TMService.asmx for the Topic Maps Web Service and NpclSchemaService.asmx for the NPCL Web Service. These endpoints provide a WSDL description if you invoke an HTTP GET on them with a single parameter "wsdl" - e.g. http://localhost/tmws/TMService.asmx?wsdl.
From the WSDL file you can generate the client-side proxy for accessing the web service. In .NET this is done using the wsdl.exe tool. For your convenience we have provided a .NET assembly, serviceclient.dll. This assembly contains client stubs for the Topic Maps Web Service and NPCL Web Service as well as classes for creating and serializing / de-serializing the XML structures that are used as parameters and return values for the web service operations.
The following code shows a method that invokes the
GetTopicsByName operation on the Topic Maps Web Service and
processes the response. The sample code shown here uses the
utilities provided by the serviceclient.dll assembly. The full code
for this example can be found in
examples/CS/WebServices/TopicsByNameSOAP. As
the code below shows, the response from the web service can be
deserialized into the appropriate class from the
NetworkedPlanet.WebServiceClient.Tmws namespace (for TMWS
operations) or NetworkedPlanet.WebServiceClient.Npcl namespace (for
NPCL Web Service operations) - there are also a set of common
structures for reporting lists of results and/or errors in the
NetworkedPlanet.WebServiceClient.Common namespace.
Example 5. Calling SOAP Web Services From C#
using System;
using System.Web.Services.Protocols;
using System.Xml;
using System.Xml.Serialization;
using NetworkedPlanet.WebServiceClient;
using NetworkedPlanet.WebServiceClient.Tmws;
using NetworkedPlanet.WebServiceClient.Common;
private static void ProcessRequest(string endpointUrl, string tmName, string queryString)
{
// Create a new TMWS SOAP client bound to the specified endpoint.
TMSClient tmwsClient = new TMSClient(endpointUrl);
try
{
XmlNode results = tmwsClient.GetTopicsByName(tmName, queryString);
XmlSerializer ser = new XmlSerializer(typeof(TopicMapFragment));
TopicMapFragment resultsFragment = ser.Deserialize(new XmlNodeReader(results)) as TopicMapFragment;
foreach(Topic t in resultsFragment.topiclist)
{
if (!t.stub)
{
System.Console.WriteLine("Topic {0}: {1}", t.oid, t.names[0].namestring);
}
}
}
catch (SoapException ex)
{
if (ex.Detail != null)
{
// SoapExceptions from TMWS will usually contain an XML fragment with a detailed description of the error
// If the SoapException was raised due to a TMWS error, the SOAP detail element will contain
// results structure which can be deserialized to extract information.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(ex.Detail.OwnerDocument.NameTable);
nsmgr.AddNamespace("res", "http://www.networkedplanet.com/schema/ws-results");
XmlElement resultsEl = ex.Detail.SelectSingleNode("res:results", nsmgr) as XmlElement;
if (resultsEl != null)
{
// We have a results element which can be deserialized to an
// instance of the NetworkedPlanet.WebServiceClient.Common.ResultListType class
XmlSerializer ser = new XmlSerializer(typeof(ResultListType));
ResultListType resultList = ser.Deserialize(new XmlNodeReader(resultsEl)) as ResultListType;
foreach(ResultType result in resultList.result)
{
if (result.isError && result.error != null)
{
System.Console.Error.WriteLine("\nError: {0}\n {1}", result.error.code, result.error.message);
if (result.error.cause != null)
{
foreach(CSharpException cause in result.error.cause)
{
System.Console.WriteLine(" Cause: {0}", cause.message);
}
}
if (result.error.action != null)
{
foreach(Action action in result.error.action)
{
System.Console.Error.WriteLine(" Corrective Action: {0}", action.Value);
}
}
}
}
}
else
{
// Just display the contents of the SOAP fault details element.
System.Console.Error.WriteLine("Error detail:\r\n" + ex.Detail.OuterXml);
}
}
}
}The following code shows a method that invokes the
GetTopicsByName operation on the Topic Maps
Web Service and processes the response. The sample code shown here
uses the utilities provided by the serviceclient.dll assembly. The
full code for this example can be found in
examples/VB/WebServices/TopicsByNameSOAP. As
the code below shows, the response from the web service can be
deserialized into the appropriate class from the
NetworkedPlanet.WebServiceClient.Tmws namespace (for TMWS
operations) or NetworkedPlanet.WebServiceClient.Npcl namespace (for
NPCL Web Service operations) - there are also a set of common
structures for reporting lists of results and/or errors in the
NetworkedPlanet.WebServiceClient.Common namespace.
Example 6. Calling SOAP Web Services from VB
Imports System.Xml
Imports System.Web.Services.Protocols
Imports NetworkedPlanet.WebServiceClient
Imports NetworkedPlanet.WebServiceClient.Tmws
Imports NetworkedPlanet.WebServiceClient.Common
...
Sub DoRequest(ByVal endpointUrl As String, ByVal tmName As String, ByVal queryString As String)
Dim tmwsClient As New TMSClient(endpointUrl)
Try
Dim responseXml As XmlNode
responseXml = tmwsClient.GetTopicsByName(tmName, queryString)
Dim ser As System.Xml.Serialization.XmlSerializer
ser = New System.Xml.Serialization.XmlSerializer(GetType(TopicMapFragment))
Dim results As TopicMapFragment
results = ser.Deserialize(New XmlNodeReader(responseXml))
Dim t As Topic
For Each t In results.topiclist
If (Not t.stub) Then
System.Console.WriteLine("Topic {0} : {1}", t.oid, t.names(0).namestring)
End If
Next
Catch ex As SoapException
If Not (ex.Detail Is Nothing) Then
Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(ex.Detail.OwnerDocument.NameTable)
nsmgr.AddNamespace("res", "http://www.networkedplanet.com/schema/ws-results")
Dim resultsEl As XmlElement = ex.Detail.SelectSingleNode("res:results", nsmgr)
If Not (resultsEl Is Nothing) Then
Dim ser As System.Xml.Serialization.XmlSerializer = New System.Xml.Serialization.XmlSerializer(GetType(ResultListType))
Dim results As ResultListType = ser.Deserialize(New XmlNodeReader(resultsEl))
Dim result As ResultType
For Each result In results.result
If result.isError Then
System.Console.Error.WriteLine("ERROR: {0}", result.error.code)
System.Console.Error.WriteLine(" {0}", result.error.message)
If Not (result.error.cause Is Nothing) Then
Dim cause As CSharpException
For Each cause In result.error.cause
System.Console.Error.WriteLine(" Cause: {0}", cause.message)
Next
End If
If Not (result.error.action Is Nothing) Then
Dim action As Action
For Each action In result.error.action
System.Console.Error.WriteLine(" Corrective Action: {0}", action.Value)
Next
End If
End If
Next
Return
End If
End If
System.Console.Error.WriteLine("Error Detail: {0}", ex.Detail.OuterXml)
End Try
End Sub