Supported Data Types in Server Web Services
Web service parameters may consist of any of the following:
- Fundamental data types - these are the built-in simple data types (e.g. string, integer)
- Struct data types - these are custom data types created using the struct command (e.g. tMyOrder)
- Arrays - these can be arrays of fundamental or struct data types (e.g. string[], integer[][], MyOrder[])
- XmlHandle - this is a special type that indicates that the data is passed as XML
Structs, Arrays, and XmlHandle data types can only be used with Document style web services (pbDocumentStyle = true).
Fundamental Data Types
The following fundamental DataFlex data types can be used as parameters and return types in web services with all data formats:
- String
- Number
- Date
- Integer
- BigInt
- Real
- Boolean
- Time
- DateTime
- Float
- Char
- UChar
- Short
- UShort
- UInteger
- UBigInt
- Currency
- Decimal
Any of these data types may be passed or returned in a web service. All of these data types will map to an appropriate XML data type as defined by the XML schema definitions. It is not expected that you will need to use most of these data types. As with any DataFlex application, you will primarily use String, Number, Date, and Integer.
Here are several very simple web service operations using various data types:
{ Published = True }
Function Echo String echoString Returns String
Function_Return echoString
End_Function
{ Published = True }
Function SayHello String sName Returns String
String sReturn
Move ("Hello," * sName) to sReturn
Function_Return sReturn
End_Function
{ Published = True }
Function TestDateTime DateTime dDateTime Returns String
String sReturn
Move ("The datetime in DataFlex locale is" * String(sDateTime)) to sReturn
Function_Return sReturn
End_Function
Struct Data Types
A web service parameter may be a custom defined type created using the struct command. Using struct parameters allows you to pass and return complex data (e.g. an order) as a single parameter. The struct members may consist of any of the allowed fundamental data types or other structs. Struct members may be defined as arrays.
Note that struct data types for input parameters can only be used when calling the web service from a SOAP client. Struct data types for return values can be used with all data formats and clients, including JSON.
This sample shows how to define and return struct data.
struct tCustomerInfo
integer iCustNumber
string sName
string sCustAddress
string sCity
string sState
string sZip
string sPhoneNumber
string sFaxNumber
string sEmailAddress
real rCreditLimit
real rPurchases
real rBalance
string sComments
string sStatus
end_struct
{ Published = True }
Function GetCustomerInfo integer iCustNum Returns tCustomerInfo
tCustomerInfo CustomerInfo
// this finds the customer and fills the struct data
Get CustomerInfo iCustNum to CustomerInfo
Function_Return CustomerInfo
End_Function // GetCustomerInfo
The following example is passed a more complex struct parameter that contains a member that is, itself, an array of structs.
// Order Detail
struct tOrderDet
string sItemID
integer iQty
real rUnitPrice
real rPrice
end_struct
// Order
struct tOrder
integer iOrderNumber
integer iCustNumber
date dOrdDate
string sTerms
string sShipVia
string sOrderedBy
string sSalesPerson
real rOrderTotal
tOrderDet[] ArrayOfDetails
end_struct
{ Published = True }
Function SaveOrderInfo tOrder TheOrder Returns Boolean
Boolean bSuccess
Get SaveTheOrder TheOrder to bSuccess
Function_Return bSuccess
End_Function
Array Data Types
Any web service parameter may be defined as an array. Arrays may be based on fundamental data types or struct types. Arrays may be single or multi-dimensional. Note that not all web service clients are capable of supporting multi-dimensional arrays.
Note that arrays for input parameters can only be used when calling the web service from a SOAP client. Array types for return values can be used with all data formats and clients, including JSON.
This sample is passed an array of customer numbers and returns an array of struct customer information.
{ Published = True }
Function SelectedCustomerInformation integer[] iCustomers Returns tCustomerInfo[]
tCustomerInfo[] Customers
integer i iCustomerCount
Move (SizeOfArray(iCustomers)) to iCustomerCount
For i from 0 to (iCustomerCount - 1)
// this finds a customer and fills an array element of struct data
Get CustomerInfo iCustomers[i] to Customers[i]
Loop
Function_Return Customers
End_Function
XmlHandle Data Type
A special data type, XmlHandle, may be defined as a parameter. The XmlHandle data type should only be used with web services. It is used when you define a function’s parameter or return data type.
Function DelCustomerXMLList XmlHandle CustomerList Returns XmlHandle
Defining this data type in a web service function indicates that the data being passed and returned is an object handle pointing to an XML DOM object (based on the cXmlDomDocument class). This provides an easy mechanism for passing data as pure XML. Within your program, you treat an XmlHandle data type exactly the same way you would treat any object handle. The object can be parsed and processed using the standard methods provided for handling XML DOM objects.
The one important distinction about this data type is that the DataFlex web services module will automatically handle the disposal of these objects when they are no longer needed. You do not need to destroy these objects yourself.
Note that XmlHandle for input parameters can only be used when calling the web service from a SOAP client. XmlHandle for return values can be used with all data formats and clients. If XmlHandle for return value is used in combination with requesting JSON output, the XML is encoded as a JSON string before returned.
For example, this web service operation is passed an XML document containing customer information. The service will search for customers to be deleted and attempt to delete these based on the rules in the data dictionary. It will then return an XML document containing a list of remaining customers. Notice that the XML data is passed in and out as objects.
{ Published = True }
Function DelCustomerXMLList XmlHandle CustomerList Returns XmlHandle
Integer bOk i iItems
Handle hoRoot hoList hoCust hoWrapper hoXml1 hoRoot1
String sDel sNumber
Handle hoCustomerDD hoXML
Move Customer_dd to hoCustomerDD
If not CustomerList Function_Return 0
Get DocumentElement Of CustomerList To hoRoot
// create node list of all customers
Get FindNodeList Of hoRoot "Customer" To hoList
Get NodeListLength Of hoList To iItems // number of items in our node list.
Decrement iItems
// go through array looking for customers to delete
For i From 0 To iItems
Get CollectionNode Of hoList i To hoCust
// if attribute "Delete" is "Y" we will delete it
Get AttributeValue Of hoCust "Delete" To sDel
If (sDel = "Y") Begin
// attempt to delete customer
Get ChildNodeValue Of hoCust "Number" To sNumber
Send Clear of hoCustomerDD
Move sNumber to Customer.Customer_number
Send Find of hoCustomerDD eq 1
If (found) Begin
Send Request_delete of hoCustomerDD
If not (err) Begin
Get RemoveNode Of hoRoot hoCust To hoCust
End
End
End
Send Destroy Of hoCust
Loop
Send Destroy Of hoList
Function_Return CustomerList
End_Function
Using XmlHandle versus Using Struct/Array Data Types
Passing data as pure XML has advantages and disadvantages. This provides a mechanism for passing and returning complex data. There are times when this type of complex data is most efficiently processed as an XML DOM object.
The disadvantage of using XML as a parameter is that the data is not fully defined within the WSDL description. The WSDL document simply knows that the data is a well-formed XML document. A second disadvantage of passing XML is that the developer on the server and on the client will have to parse the XML data themselves.
If you need to pass complex data that is fully defined within the WSDL description, you can pass the parameters as structs and arrays. In general, it is easier to work with complex data as structs and arrays. The above example could easily be rewritten to use an array of structs as follows:
struct tCustomerList
integer iCustomerNumber
string sCustomerName
Boolean bDelete
end_struct
{ Published = True }
Function DelCustomerXMLList tCustomerList[] CustomerList Returns tCustomerList[]
tCustomerList NewCustomerList
Integer i iCustomerCount iNewCount
Boolean bWasDeleted
Move Customer_dd to hoCustomerDD
Move (SizeOfArray(CustomerList)) to iCustomerCount
// go through node list looking for customers to delete
For i From 0 To (iCustomerCount - 1)
If CustomerList[i].bDelete Begin
// attempt to delete customer
Send Clear of hoCustomerDD
Move CustomerList[i].iCustomerNumber to Customer.Customer_number
Send Find of hoCustomerDD eq 1
If (found) Begin
Send Request_delete of hoCustomerDD
Move (not(err)) to bWasDeleted
End
End
Else Begin
Move False to bWasDeleted
End
If not bWasDeleted Begin
Move CustomerList[i] to NewCustomerList[iNewCount]
Increment iNewCount
End
Loop
Function_Return NewCustomerList
End_Function
Passing Parameters By Reference
A web service method may pass and return information by reference. A by-reference parameter is referred to as an in/out parameter - the same parameter is used to pass data in and data out. A by-reference parameter is defined by using the BYREF keyword in the method declaration.
Note that by-reference parameters can only be used when calling the web service from a SOAP client.
The following sample passes an order as a BYREF parameter. The order is passed in, saved, refreshed, and then passed back to the caller. In addition, the normal return parameter is used to return a Boolean indicating the status of the save.
{ Published = True }
Function SaveOrderInfo tOrder BYREF TheOrder Returns Boolean
Boolean bSuccess
Get SaveTheOrder TheOrder to bSuccess
If bSuccess Begin
Get RefreshTheOrder to TheOrder
End
Function_Return bSuccess
End_Function
Note:
The DataFlex client web service parser and class handle in/out parameters properly. However, many web clients are not capable of supporting in/out parameters. If you wish to make a web service available to the widest number of clients, you may want to avoid using by-reference methods. With the availability of structs, there is little reason to use in/out parameters.