Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro


:P
On this page:

I’ve been working on some demos with the SOAP Toolkit and one of the things that does not appear to be easily accomplished is passing complex data to a Web Service from a Visual FoxPro (or other COM client application). If you call a Web Service that expects a complex type on the Web Service side – for example a DataSet or a simple Business Entity object – you can’t just simply pass an object reference and have the MSSOAP client serialize it.

 

In order to pass an object you either have to create the SOAP response manually using the low level SOAP API (fair amount of code), create a special serializer yourself (complex process) or pass the XML content for the object in the form of a NodeList.

 

The latter of these I wasn’t aware of until today. In fact, in the past I had pretty much resigned myself to creating server side Web Services that accept string parameters that allow XML to be passed in and be parsed into the proper objects on the server side.

 

This works OK if you are in control of the server side, but there’s a fair amount of overhead in the double encoding that occurs of the XML string (once encoding into XML, then encoding the XML into an XML Safe string).

 

It turns out that you CAN pass XML content directly to the SOAP Parser as a parameter by creating an XMLNodeList of the XML content that is to be passed. This still isn’t exactly transparent, but at least this mechanism allows for calling a SOAP Web Service where a complex parameter is required assuming we can assemble the proper XML.

 

The most common scenario I’ve been running into is passing a DataSet to a Web Service. The following example demonstrates posting changes made to a VFP Cursor (Authors from the Pubs Sql Server Database)  and saving them back to the server by passing a DataSet to the UpdateAuthorData() method on the server.

 

oSOAP = CREATEOBJECT("MSSOAP.SoapClient30")

oSOAP.MSSoapInit(lcWSDLUrl)

 

SELE AUTHORS  && Assume Authors is loaded and changes where made

 

*** Generate the DiffGram DataSet XML

LOCAL oXA as XMLAdapter

oXA = CREATEOBJECT("XMLAdapter")

oXA.UTF8Encoded = .t.

oXA.AddTableSchema("Authors")

oXA.IsDiffgram = .T.

 

lcXML = ""

oXA.ToXML("lcXML",,.f.,.T.,.T.)

 

*** Convert the XML into a NodeList

loDOM = CREATEOBJECT("MSXML2.DomDocument")

loDom.LoadXMl(lcXML)

loNodeList = loDom.DocumentElement.ChildNodes()

 

*** Retrieve authors - returns DataSet returned as NodeList

LOCAL loException as Exception

loException  = null

 

TRY

   *** Pass the NodeList as the DataSet parameter

   llResult =  oSOAP.UpdateAuthorData(loNodeList)

CATCH TO loException

   llError = .t.

ENDTRY

 

*** Always check for errors

IF !ISNULL(loException)

   lcError = oSOAP.FaultString

   if EMPTY(lcError)

      lcError = loException.Message

   ENDIF

   ? lcError

   ? loException.ErrorNo

   RETURN

ENDIF

 

*** Print the reslt - .t. or .f.

? llResult

RETURN

 

The key features here are taking the XML returned from the XMLAdapter and creating a NodeList from it and then passing that Nodelist to the Web Service function UpdateAuthorData() which expects a DataSet as its input value.

 

This code:

 

loDOM = CREATEOBJECT("MSXML2.DomDocument")

loDom.LoadXMl(lcXML)

loNodeList = loDom.DocumentElement.ChildNodes()

 

Loads the XMLAdapter generated DiffGram XML into a DOM object and then retrieves the ChildNodes collection. The Soap client provides the root node for the parameter, and the detail is parsed into it from the passed NodeList which gets embedded into the SOAP Document as raw XML. Note that you have to make sure you generate your XML with the proper Encoding – UTF8 typically.

 

The same mechanism can be applied for objects passed to the Web Service from the client. All complex types are passed as embedded XML fragments and this mechanism allows you to directly embed this data.

 

This approach still doesn’t solve the problem of parsing objects into XML for transfer in the first place, but at least it gives us the ability to generate the appropriate XML as needed and at least be able to call these methods if string methods aren’t available. For DataSets this process is nice because VFP can generate the appropriate XML for us directly. With other objects you probably will have to manually create the XML or use a tool like wwXML to help with serialization.


The Voices of Reason


 

Joe Gori
March 10, 2005

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

Great Article, I am currently using VFP 8, and was wondering if there is a document or resource where i could figure out how to generically (sp) serialize an object for passing from VFP to a web service. i.e. the web service takes a complex object and i need to pass it (obviously from your article in the nodelist) in the node list. I've done it with simple objects but layered or complex objects gets tough.

Rick Strahl
March 10, 2005

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

You'll also want to have a look at this article:

http://www.west-wind.com/presentations/foxpronetwebservices/foxpronetwebservices.asp

which goes into more details about passing complex data including nested objects. It also points at wwSOAP which can help parse complex objects returned from the server.

Paul V
June 30, 2005

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

I am using VB.Net and can't find an XMLAdapter. Is there a VB.Net equivalent or am I barking up the wrong tree?


David
July 14, 2005

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

How does one pass xml when NOT using a complex item?

I have a web method that returns XML which I manually construct using XmlTextWriter and a stream. One reason for doing this is that I want to include a DTD reference (it's part of a pre-arranged standard that I I don't control) in the XML. WHen I return the XML I created (the method return type is XmlNode) I notice that a xmlns="" attribute is added. How can I just handle passing XML, formatted the way I want it? Obviously, I could pass the results as a string but do not want to do that.

Tina
August 05, 2005

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

Does anybody here have an idea as to how to i acheive the same using vb.net?

Paul G
January 25, 2006

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

I'm having a tough time with this. I've got it to pass an empty dataset with the correct schema to a .Net web service. I just can't seem to get it to pass the data rows along with it. How does the data contain in Authors make it into the XML?

Thanks a million for all of your work over the years. Whenever we are attempting something new in Foxpro, you site almost always has the answer for which we are looking.

Andew
February 03, 2006

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

Thank you! You are a life saver.

fikret
September 28, 2013

# re: Passing Complex Objects and XML data to Web Services with MSOAP with Visual FoxPro

Thank you! even years later still works.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2025