Using the FoxPro Proxy Class to call the Web Service

The Proxy Generator creates Web Service Proxy classes based on the wwDotNetBridge class for interfacing to the .NET assembly (dll) that that the WSDL generator produces. Most of the concepts described in this topic are about wwDotnetBridge behavior. For more detailed info please check out the wwDotnetBridge White Paper.

Once the .NET and FoxPro Proxies have been generated you can now make Web Service calls against the Web Service with ease. To use the service is as easy as the following code:

*** Load the Proxy and Support Class Libraries
DO WebStoreServiceProxy

*** Create an instance of the Proxy
LOCAL loService as WebStoreServiceProxy
loService = CREATEOBJECT("WebStoreServiceProxy","V4") && Optionally specify .NET Version

*** Downloads an object - inventory item
LOCAL loItem as WebStoreService.wws_itemRow
loItem = loService.DownloadInventoryItem("WSDLGenerator")

*** Check for Errors if necessary
IF loService.lError
   ? loService.cErrorMsg  

*** Intellisense should work here if compiled with the COM Registration option locally
? loItem.Sku
? loItem.Descript

*** Release service resource
loService = null

Required Dependencies

If you run the Web Service Proxy out of any directory other than the install directory make sure that you copy the required dependencies in to the FoxPro Path. For more information please see Files Required for Compilation and Distribution. The generation Wizard includes an option at the end that can copy all generated files plus the required dependencies into a folder of your choice to make it easy to create a distributable build that can easily be added into your own applications.

The WebStoreServiceProxy class is a FoxPro class so it behaves as you would expect any other FoxPro class to behave. You simply call a method on the service, pass your parameters and return a result.

Notice in the method above the result is a complex type of type WebStoreProxy.wws_itemsRow and we're accessing it without any setup or configuration. It just works.

Behind the scenes the service calls are made over COM, but note that no COM registration of the .NET component is required. wwDotNetBridge provides the .NET interface to the service proxy class and it does so through .NET internally and so no registration is required which makes it easy to deploy your application using these proxies: Simply copy your proxy dll with the rest of your app and you're done. XCopy deployment.

Passing Complex Types

In the previous example I returned a complex inventory item object and FoxPro could deal with this object directly. When the service returns an object that object comes back as COM object and can be manipulated easily and you can use that same type to pass back to .NET:

*** update an existing item
loItem = loService.DownloadInventoryItem("WCONNECT50")
loItem.Descript = "Updated Item Description"
loService.UploadInventoryItem(loItem)    && Note: Service actually doesn't save (no spamming!) but you get a response

However a more common scenario requires you to actually create an instance of a type first and pass that to the Web Service. This process requires that you create an instance of the type first:

*** Create an instance of the wws_itemsRow object
LOCAL loItem as WebStoreService.wws_itemRow
loItem = loService.oBridge.CreateInstance("WebStoreService.wws_itemsRow")

*** Intellisense should work here if compiled with the COM Registration option locally
loItem.Sku = "NewItem"
loItem.Descript = "Another new item"
* ... more properties set

This works just as you would expect - the item is created and you can set properties and then use it as an input parameter to the service call. The object again is a COM object and it's of the type that the .NET proxy expects to receive. Note that if the object you are creating contains subobjects - objects defined on a child property - you will need to explicitly instantiate those child objects as well or else these child properties will remain null or whatever their default values are.

Note the use of loService**.oBridge** which is an instance of a wwDotnetBridge object which provides .NET services to Visual FoxPro. Here it creates an instance of the class based on it's .NET type name. I'll come back to how the instantiation works, but let's first look at how you can find out how to find this type name.

How do I know what Type to instantiate?

The trickiest part about instantiating new types in any complex Web Service is knowing which type you actually need to instantiate for a new object. How do you know that you have to use WebStoreService.wws_itemsRow in the example above? The easiest way to discover types is by looking at the .NET Proxy assembly with Reflector.

You can find Reflector in c:\program files\West Wind Web Service Proxy Generator for Visual FoxPro\tools folder as Reflector.exe. Open Reflector and use Open to navigate and open the generated .NET Proxy assembly (webStoreServiceProxy.dll in this example)

If you open up the assembly in Reflector, the first thing you'll want to do is find the service and the method you want to call:

You can find the parameter list and see the type that is used for the method parameter. Each type is usually clickable and you can follow the link then to the actual type definition:

On the bottom you can see the full typename that you can use with loService.oBridge.CreateInstance() to create a new instance of the type and this is the key thing. It's namespace.classname that makes up this definition and the namespace is what you defined during the generation of the Web Service Proxy.

You can also see the properties of this type at a glance here which is useful. You can use the back and forward buttons to quickly navigate a hierarchy.

If you ever need to use a real complex service like the Amazon e-Commerce service for example, you will really appreciate how useful this functionality is in letting you quickly find types for instantiation.

How does Object Instantiation Work

Ok so how does object instantiation work?

All access to the .NET proxy component is done via COM using wwDotNetBridge as the intermediary which provides for the ability to instantiate COM components without them to be registered as COM components. It also provides a host of other service to allow access to .NET types and members that normally are not accessible via COM by acting as a proxy for COM calls against .NET components.

When you call loService.oBridge.CreateInstance() wwDotNetBridge instantiates a .NET component and passes it back over COM. The instance IS a full COM instance but the difference is that it was instantiated by the wwDotNetBridge component running inside of the .NET Runtime, rather than through normal COM activation. This bypasses the registry and COM activation so that components do not need to be registered.

Objects that come back are still COM objects as usual so you can call methods on them, access properties and so on. wwDotNetBridge allows you also indirectly access methods and properties on the same component, but this is only necessary if there is something that doesn't work directly. Some things that don't work directly are accessing structures (value types), some types of arrays, accessing static methods or properties, enumerated values or overloaded methods. All these things cannot be done directly with COM Interop but can be done through the wwDotNetBridge proxying. You may or may not need these more advanced features depending on the complexity of your service, but wwDotNetBridge can be used in other more generic environments as well.

© West Wind Technologies, 2004-2017 • Updated: 06/07/17
Comment or report problem with topic