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