I have discovered a problem when calling an extension codeunit function via NAV 2009 SP1 web services. The function is coded to return a BigDecimal, but the result of the web service call is an array of BigDecimals. The array has two populated values (in positions 0 and 1) that are the same (each value is the result I would have expected).
Here is the code for the codeunit function.
PROCEDURE CustomerSalesToDate@1000000001(Cust@1000000000 : Record 18) ToDateSales : Decimal;
BEGIN
WITH Cust DO BEGIN
IF CurrentDate <> WORKDATE THEN BEGIN
CurrentDate := WORKDATE;
END;
SETRANGE("Date Filter",0D,CurrentDate);
CALCFIELDS("Sales (LCY)");
EXIT("Sales (LCY)");
END;
END;
Interrogation of the WSDL reveals that the operation should return a BigDecimal (not an Array of BigDecimals)
<xsd:element name="CustomerSalesToDate_Result">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="1" maxOccurs="1" name="return_value" type="xsd:decimal" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<operation name="CustomerSalesToDate">
<operation soapAction="urn:microsoft-dynamics-schemas/page/customerwidget:CustomerSalesToDate" style="document" xmlns="
http://schemas.xmlsoap.org/wsdl/soap/" />
<input name="CustomerSalesToDate">
<body use="literal" xmlns="
http://schemas.xmlsoap.org/wsdl/soap/" />
</input>
<output name="CustomerSalesToDate_Result">
<body use="literal" xmlns="
http://schemas.xmlsoap.org/wsdl/soap/" />
</output>
</operation>
The result I am receiving from the above function is BigDecimal[] with two values {43356.45, 43356.45}
I have another function in this codeunit that returns an array of 5 BigDecimals. When calling the operation via a Web Service, it returns an array of 10 values (a pair of each value I was looking for.
Here is the first line of the codeunit function
PROCEDURE CustomerStats@1000000003(Cust@1000000000 : Record 18;CustDateChoice@1000000001 : 'Current,ThisFY,LastFY') CustStats : ARRAY [5] OF Decimal;
Here is the result that is returned.
[1896.6, 1896.6, 686.67, 686.67, 64.74, 64.74, 273849.72, 273849.72, 0, 0]
So, am I doing something wrong? Is this a bug in NAV Web Services? Or maybe it is an undocumented feature to insure the numbers accuracy by returning two of them so you can easily see that they are equal.
My development is done under Mac OS X in Java using the Eclipse IDE. I'm also calling the service using dynamic discovery / invocation (stubs? we don't need no stinking stubs!), So I would like to ask my .Net/C# Brethern if they have ran into this problem, or can it be duplicated in the .Net side of the house.
I'll append some Java code to show how the operation is constructed and the call is made.
public void initializeCustomerSalesToDateOperation() throws Exception{
// Customer Sales Operation (Returns Customer Sales for a date period for the customer key)
// Check the binding to make sure the anticipated operation exists and is consistent with our understanding
BindingOperation bindingOperation = navBinding.getBindingOperation("CustomerSalesToDate","CustomerSalesToDate", "CustomerSalesToDate_Result");
if (bindingOperation == null){
customerSalesToDateOperation = null;
return;
}
// Build the Operation
OperationDesc oper = new OperationDesc();
oper.setName("CustomerSales");
// Set the Input Parameters
ParameterDesc param;
param = new ParameterDesc(new QName(nameSpaceUri, "cust"),
org.apache.axis.description.ParameterDesc.IN,
new javax.xml.namespace.QName("
http://www.w3.org/2001/XMLSchema", "string"),
java.lang.String.class, false, false);
oper.addParameter(param);
// Set the Return Type
oper.setReturnType(new QName("
http://www.w3.org/2001/XMLSchema", "decimal"));
oper.setReturnClass(java.math.BigDecimal.class);
oper.setReturnQName(new QName(nameSpaceUri,"return_value"));
oper.setStyle(org.apache.axis.constants.Style.WRAPPED);
oper.setUse(org.apache.axis.constants.Use.LITERAL);
customerSalesToDateOperation = oper;
}
Here is the actual call, hacked to return the first value in the array that was unexpectedly returned.
/**********************************************************************
*** CustomerSalesToDate - Extended (Codeunit) Method to retrieve ***
*** the value of flow field Sales To Date from a customer ***
*** parameter - key - a key from a retrieved ***
*** instance of a Customer (WMSNavRecordObject). ***
***
@throws AxisFault ***
*
@throws Exception ***
*********************************************************************/
public BigDecimal customerSalesToDate (String key) throws AxisFault, Exception{
cardPageCall.setOperation(customerSalesToDateOperation);
cardPageCall.setUseSOAPAction(true);
cardPageCall.setSOAPActionURI(nameSpaceUri + ":CustomerSalesToDate");
cardPageCall.setEncodingStyle(null);
cardPageCall.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
cardPageCall.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
cardPageCall.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
cardPageCall.setOperationName(new javax.xml.namespace.QName(nameSpaceUri, "CustomerSalesToDate"));
try {
java.lang.Object _resp = cardPageCall.invoke(new java.lang.Object[] {key});
if (_resp instanceof java.rmi.RemoteException) {
throw (java.rmi.RemoteException)_resp;
}
else {
// extractAttachments(cardPageCall);
try {
ArrayList respArray = (ArrayList) _resp;
if (respArray.get(0) instanceof BigDecimal) return (BigDecimal)respArray.get(0);
else return new BigDecimal(0);
} catch (java.lang.Exception _exception) {
return (BigDecimal) org.apache.axis.utils.JavaUtils.convert(_resp, BigDecimal.class);
}
}
} catch (org.apache.axis.AxisFault axisFaultException) {
throw axisFaultException;
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
On the function that should return 5 but actually returns 10 values, I Hacked it by multiplying the index that the value should have been in by 2.
Comments
Co-Founder Liberty Grove Software
Author: Programming Microsoft Dynamics NAV (V5.0), 2009, 2013
I agree it can be worked around easily enough, but it may take some cleanup effort if the problem is fixed, or the secret feature is taken away from us.
http://www.wmmatthewstreet.com
I found the same problem and seems it's a trouble with decimal data type.
If the Codeunit use is only for web service yo can return a text. In that case only return one return value, but in the definition schema the data type is string of course.
I found another trouble when you try to use XMLports like parameters in codeunit's methods for web services publication. The definition schema that generated Navision can be treated with .NET with success but there is a mistake using name spaces and have to be modified if you want to consume with another system.
What worked for me was setting the MaxOccurs property of the XMLport field to "Once" instead of the default "Unbound" option. This should return one single element instead of an array.
Thank u