[ 1 ] Once this result is retrieved the code loops through the portfolio for
the user again and retrieves a node reference to each of the symbols by
using and XSLT query to retrieve each of the symbol nodes: From here the node can be imported into an object using wwXML and the
low level ParseXMLToObject() method which takes an XML node as input and
parses the properties below it into the object provided: At this point the object is filled with the appropriate data and the
portfolio record in the table is updated with this data using a standard
VFP REPLACE command to fill in the data from the loQuote object. So far you may find that what I presented doesn't show huge
improvements over what you can accomplish with straight XML messaging. The
main reason is that some of the tools like wwXML's data conversions can
make short work of generating and importing XML easily. However, if you're
not using high level tools SOAP's advantages become much more obvious. To
demonstrate I used SOAP to retrieve a single stock quote from the HTML
based Web page. In this scenario, only client side Jscript code in Internet Explorer
5.0 and later is used to make the SOAP method call and display the data in
the browser without refreshing the entire Web page. If you look at figure
3 again, you can see the Get Single Quote textbox and the Go button. The
Go button points to some Jscript in the Web page: When you click on the Go button, a SOAP call is initiated from the
browser. The actual library functions for this are contained in wwsoap.js
(you can look at that from the sample page as well there's a link on the
bottom for it). The key features are the AddParameter and CallMethod
functions which work like their counterparts in wwSOAP. The difference is
that Jscript doesn't support objects so these functions are not set up as
methods. The Jscript SOAP implementation I created is also very basic and
rather crude, but it will work well against the Web Connection Web Service
and MS SOAP clients. wwSOAP.js uses the XMLHTTP component to communicate
with the Web Server and retrieve the data. Since Jscript doesn't support objects and GetStockQuote() returns and
object, the Jscript wwsoap implementation returns an XML string as a
result value. This string is loaded into the XMLDOM and then the
individual values are retrieved and build up into an HTML string, which is
simply replaced into the HTML document. The entire section below the Quote
text box is dynamically generated using a <span> tag whose .innerHTML
property is set by the HTML created.
If you want to build browser applications that use SOAP or any kind
of XML based communication the Microsoft.XMLHTTP component is the
tool to use when accessing HTTP content over the Web. XMLHTTP
provides complete HTTP access with a few lines of code.
Unfortunately making calls against a different domain than the one
that you got the page from results in a nasty error message that
tells you of cross-domain data access. By default IE's security
settings disable cross-domain access and simply fails.
There are two ways to fix this:
1) Go into the security settings for IE and configure cross-domain
access so that it is allowed or at the very least prompts you
instead of simply failing.
2) Set up the other domain that is accessed as a trusted zone in
Internet Explorer. This bypasses any of the security checks that
normally occur.
For public access applications neither of these options are very
pleasant. In my own apps, I've had to resort to putting notes on the
screen to let people know how to configure their browsers.
This is one reason why SOAP is important you can use SOAP on the
server side to consolidate data from multiple sources and then feed
the combined data from the current Web site, which avoids the
cross-domain problems.
The examples I've shown where all built
You can take the StockService Web Service we created and use it with MS
SOAP by simply compiling the Web Service into a COM object (make sure you
add all dependent files to the project they won't automatically get
pulled in) and then running the MS SOAP SDL Wizard to generate the SDL and
ASP files. You can look at the MS SOAP article on details for this.
Figure 8 The SDL Creation Wizard takes a
Web Service class and generates a An SDL file basically describes the functionality of a Web Service and
acts as a sort of type library. The MS SOAP Toolkit actually requires use
of an SDL file both on the client and the server side of a Web Service
implementation, so any type of Web Service that wants to be accessed
through MS SOAP must expose an SDL file. The SDL Wizard generates an SDL file from any PRG file that contains
an embedded OLEPUBLIC class with the same name as the file. So, if I have
StockService.wwSOAP and a StockService class inside of it an SDL file
called StockService.xml is generated in the same directory as the Web
Service. Note that .wwSOAP files are really just PRG files with a
different extension, so this Wizard will work on any PRG based class. What gets generated is SDL that's compatible with the MS SOAP toolkit.
Unfortunately, SDL specifications are not really specifications and
Microsoft currently has 3 different implementations of it: The MS SOAP
toolkit, the .Net implementation and the new forthcoming WSDL
specification which supposedly will be supported both by .Net and MS SOAP.
The current Wizard generates MS SOAP compatible SDL, because that is the
only shipping SDL format that you're likely to find at the moment. The generated SDL file for our Stock Service looks as follows:
There are a couple of key elements in an SDL file. The top section
describes the interface of the Web Service: The name of the methods and
the parameters it expects as well as pointers to the implementation
section of the schema. The implementation is provided below and shows in
detail what types are passed as parameters and and what return types are
returned. Note that the GetStockQuote method of the Web Service returns an
object parameter with MS SOAP does not understand, so it will fail on this
call. You can change the type manually to dt:string to work around this,
but realize that you'd have to parse the XML manually. The other important thing in the SDL file is the <address> fragment
which determines the locations of the actual Web Service request handler.
It's important that you remember to either change this value or re-run the
Wizard when you move your Web Service between a development machine and
the live Web Server because the URLs likely will change. Here I generated
it to localhost for local testing. When I put it online I'll want to call
the service on www.west-wind.com. We can test this out real quick using the MS SOAP Toolkit with the
following code: and it will correctly return me the stock quote. Note that although
the SDL file marks the return value as integer, MS SOAP will always return
a string.
I've been using SOAP on a couple of projects now and we're finding
that building Web Services is a huge timesaver, because it's real easy to
build server functionality. We're also finding that although SOAP greatly
simplifies building distributed applications in many cases, we still end
up using XML extensively asparameters for method calls in order to avoid
continuous server round trips. Most sample Web Services out there today
are returning unrealistic types of information that does not reflect
reallife applications. For SOAP to really be useful objects or other
compound data needs to be passed. Passing objects is a good option, but
for generic access this gets difficult to implement because the client
application will have to deserialize the object into an existing structure,
which requires some coupling. Object support varies greatly for the
various SOAP implementations and some, notably the MS SOAP toolkit don't
support objects at all, so passing data in XML format continues to be a
common requirement even with SOAP. There is also a mental hurdle to overcome with SOAP especially for
those of us that have used XML in distributed applications before. Raw XML
is simple and elegant and with the right tools it takes very little code
to build XML solutions without requiring SOAP in the middle. In fact, when
I first put out my SOAP implementation I asked around for some solutions
that would really highlight a SOAP interface as opposed to a custom XML
implementation. Lots of suggestions came up, but the reality is that none
of them screamed out and said SOAP is the clear choice. The examples that
were perfect for SOAP mostly revolved around simplistic examples that
passed in single values and returned a single or multiple simple results.
Most real-world applications don't work that way! This means you need to
either objects with the varying support or you're back to using XML to
pass as parameters with all the manual parsing this involves. I can live
with that since we use XML extensively in every application anyway and we
have tools like wwXML to make use of that XML nearly transparent. But
those unfamiliar with XML or not using high level tools will not see that
much of a benefit from SOAP over a custom XML implementation. The big benefit of SOAP is a common interface that is universal. SOAP
clients are already available for almost any platform and most let you
make the SOAP call with just a couple of lines of code as I've shown. .Net
takes this one step further and directly integrates remote calls into the
environment which based on compiler settings can tell whether an object is
local or remote and transparently call the remote object. As nice as that
sounds, right now .Net is the only thing that can talk to .Net even it
uses SOAP underneath the covers, as the implementation is proprietary
relying on a custom SDL file format. This will likely change by the time
.Net is ready, but right now it's just another piece in the puzzle to
figure out. On the downside when comparing SOAP to a plain XML solution is that
SOAP has more overhead. For many applications that pass complex data
around double XML parsing occurs. One to create your actual XML messages (object
packaged as parameters or return values) or XML string parameters. And
then there's the actual creation of the SOAP package and content. Request
times over the Internet are good with most examples I ran taking under 1
second including Web round trips on a slow dial-up connection. This will
be fine for most distributed applications, but it's not a replacement for
a high performance application that uses DCOM now, which on the same
network would run around 1,000 times faster making the same method call. Still, getting familiar with SOAP and Web Services now is a good idea,
because it's here to stay. Exposing your application logic with Web
Services today will make sure that those services can be consumed by
future applications that will be built around the SOAP standard.In the
future SOAP tools will become even easier than what I've shown here.
Languages will natively support SOAP so that objects can be accessed
locally or globally using the same syntax. For today, we have to do a
little more work, but we also get the benefit of full control we can
actually see what's happening under the hood. SOAP is underlying a lot of Microsoft's new technology, especially
.Net, so I would encourage you to learn more about it and start using it
as it will prepare you for what's to come. The tools are here today, so
you can use and integrate this technology today
Get to it!
Rick Strahl is president of West Wind Technologies on Maui, Hawaii.
The company specializes in Web and distributed application development and
tools with focus on Windows 2000 and Visual Studio. Rick is author of West
Wind Web Connection, a powerful and widely used Web application framework
for Visual FoxPro, West Wind HTML Help Builder and co-author of Visual
WebBuilder. He's also a Microsoft Most Valuable Professional, and a
frequent contributor to FoxPro magazines and books. He is co-publisher and
co-editor of CoDe magazine, and his book, "Internet Applications with
Visual FoxPro 6.0", is published by Hentzenwerke Publishing. For more
information please visit:
http://www.west-wind.com/.
|