Function SysOperationDataContractInfo::newParameterInfo has been incorrectly called

Problem

DictMethod, when it is running without debugger, does not correctly fetches metadata of inherited methods on a child class.
Following code:
static void VKDictMethodTest(Args _args)
{
    DictMethod  dictMethod;
    str         parmName;
    int         parmIndex = 1;


    dictMethod = new dictMethod(UtilElementType::ClassInstanceMethod, classNum(AssetProposalAcquisition), 'buildRange');

    parmName = dictMethod.parameterName(parmIndex);

    if (parmName)
    {
        info(strFmt("ParmName: %1", parmName));
    }
    else
    {
        throw error("incorrect");
    }
}
As can be seen from hierarchy browser the method buildRange is available at AssetProposal class.
Depending on the debug mode option, the execution of code above will give different results.
Debug mode: No
It does not able to fetch first parameter name.
Debug mode: When breakpoint
ParmName: _items

Impact

SysOperation framework uses DictMethod to prepare parameters for method execution
\Classes\SysOperationServiceController\getDataContractInfoObjectsInternal
protected Map getDataContractInfoObjectsInternal()
{
    SysDictClass dataContractClass;
    DictMethod dictMethod;
    int parameterCount;
    int i;
    Object dataContractObject;
    SysOperationDataContractInfo contractInfo;
    Map dataContractInfoObjects;

    dataContractInfoObjects = new Map(Types::String, Types::Class);

    dictMethod = this.getServiceOperation();
    if (dictMethod)
    {
        parameterCount = dictMethod.parameterCnt();
        for (i = 1; i <= parameterCount; i++)
        {
            dataContractObject = null;

            // This will throw an exception on types that are not supported
            this.checkAllowedServiceParameterType(dictMethod.parameterName(i), dictMethod.parameterType(i));

            dataContractObject = this.initializeServiceParameter(dictMethod, i);

            if (dataContractObject != null)
            {
                dataContractClass = new SysDictClass(classIdGet(dataContractObject));
                contractInfo = SysOperationDataContractInfo::newParameterInfo(
                    dictMethod.parameterName(i),
                    dataContractObject,
                    dataContractClass,
                    null);
                dataContractInfoObjects.insert(dictMethod.parameterName(i), contractInfo);
            }
        }
    }
    return dataContractInfoObjects;
}
And here call to SysOperationDataContractInfo::newParameterInfo fails, because DictMethod is unable to fetch parameter name and you are getting following error:
Function SysOperationDataContractInfo::newParameterInfo has been incorrectly called

This happens when we have a class hierarchy and a child class, which should be executed does not have run (or other method to execute) method, which is available at parent class.

Workarounds

1. Override the method at child class and call super
public void run(BisMessageDataContract _contract)
{
    super(_contract);
}
The method should be available at child class, which is acting

2. Install AX debugger. It is funny, but working



 

Search

About

DaxOnline.org is free platform that allows you to quickly store and reuse snippets, notes, articles related to Dynamics AX.

Authors are allowed to set their own AdSense units and "buy me a coffee" link.
Join us.

Blog Tags