A couple of days ago, I encountered this problem while calling the InventInventLocation AIF web service’s create operation.
System.ServiceModel.FaultException : Invalid document schema. The following error is reported : The element ‘InventLocation’ in namespace ‘http://schemas.microsoft.com/dynamics/2008/01/documents/InventLocation’ has invalid child element ‘InventLocationIdQuarantine’ in namespace ‘http://schemas.microsoft.com/dynamics/2008/01/documents/InventLocation’. List of possible elements expected: ‘InventLocationId’ in namespace ‘http://schemas.microsoft.com/dynamics/2008/01/documents/InventLocation’.
The error itself may actually be confusing because in this case, the InventLocationIdQuarantine field is not actually the cause of the problem. In most cases this error will appear when the order of fields is different from the one expected by the document schema. So either the field ordering is different of there are some fields missing. In this case, I was using AIF webservices (WCF services) and you can view the actual XML that was communicated to the AIF by going to the document history.
Basic – Periodic – Application Integration Framework - Document History

AIF Document History
There you can view the XML by clicking the XML button.

XML InventLocation Create Operation
Here we can see that the inventlocation field is not present in the XML.
Do note that in this Ax application we have create custom code to initiate the InventLocationId field from a numbersequence when the record is created.
To solve the error here, we need to tell the AIF engine that the InventLocationId field is not mandatory in our XML document and make sure the value gets defaulted.
This will be done here by adding defaulting logic in the Entity class but this could also be done by putting the defaulting “behavior” on the table using a strategy pattern.
Setting the field as not mandatory :
protected void initMandatoryFieldsExemptionList()
{
super();
this.setParmMethodAsNotMandatory(methodstr(AxInventLocation,parmInventLocationId));
}
Adding the defaulting logic :
protected void setInventLocationId()
{
NumberSequenceReference numberSequenceReference;
;
if (this.isMethodExecuted(funcname(), fieldnum(InventLocation, InventLocationId)))
{
return;
}
if (this.isSetMethodsCalledFromSave())
{
if (this.isFieldSetExternally(fieldnum(InventLocation, InventLocationId)))
{
if (!this.inventLocation())
{
numberSequenceReference = InventParameters::numRefInventLocationId();
this.checkNumber(numberSequenceReference.numberSequenceTable(),fieldnum(InventLocation, InventLocationId),this.parmInventLocationId());
if (numberSequenceReference.NumberSequence && numberSequenceReference.numberSequenceTable().Continuous)
{
NumberSeq::newReserveNum(numberSequenceReference).reserve(this.parmInventLocationId());
}
}
}
else
{
if (this.isFieldSet(fieldnum(InventLocation, InventLocationId)))
{
return;
}
if (!this.parmInventLocationId())
{
this.parmInventLocationId(NumberSeq::newGetNum(InventParameters::numRefInventLocationId()).num());
}
}
}
}
Now we do not need to specify the inventLocationId and the field will be defaulted to a new number from the number sequence reference.
First things first… the original post that I found about this topic can be found here : http://dynamic-ax.co.uk/DynamicsAXAlertsToMultipleUsers.aspx
But since the link to the xpo was broken , I created this post to put this online and make some minor changes. (Don’t mind some best practices stuff like labels, security keys, … because you’ll probably create your own to use )
First we create a table and form to contain the recipient list.

Event Rule Recipient List
Then an adjustment is needed in the EventCreateRule class, method Run. Here the event rule will be updated so we need to maintain the link between the EventRuleId and the recipients table.
public void run()
{
#OCCRetryCount
EventRule eventRuleDB;
// KeSae : 21/04/2010 : Alerting multiple mail recipients
EventRuleId oldRuleId;
;
try
{
ttsbegin;
select firstonly eventRuleTmp;
eventRuleDB.data(eventRuleTmp);
eventRuleDB.setDeleteRefRecId(callerRecord);
// KeSae : 21/04/2010 : Alerting multiple mail recipients
oldRuleId = eventRuleDB.RuleId;
eventRuleDB.RuleId = this.parmCreatedRuleId();
eventRuleDB.insert();
eventRuleDB.filterQuery(this.queryrun().query());
eventRuleDB.alertField([tmpEventAlertField]);
eventRuleDB.typeValue(packedEventType);
eventRuleDB.contextInfo(this.packContextInfo(eventRuleDB));
this.parmCreatedRuleId(eventRuleDB.RuleId);
// KeSae : 21/04/2010 : Alerting multiple mail recipients
// Since the RuleId changes during this process, update the link in the recipient table
NVMPEventRuleRecipients::updateRuleIdLink(oldRuleId, eventRuleDB.RuleId);
ttscommit;
this.checkForeignKey();
}
catch (Exception::Deadlock)
{
retry;
}
catch (Exception::UpdateConflict)
{
if (appl.ttsLevel() == 0)
{
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::UpdateConflictNotRecovered;
}
else
{
retry;
}
}
else
{
throw Exception::UpdateConflict;
}
}
}
The following change is adding the recipients when mailing. Class EventActionEmail, method Execute :
mappings = this.createEmailParameterMap(alertInbox,eventType,eventRule);
xmlParameters = EventActionEmail::createEmailParameterXml(mappings);
if (eventParameters.AlertTemplateId)
{
SysEmailTable::sendMail(eventParameters.AlertTemplateId
, userInfo.Language
, sysUserInfo.Email
, mappings
, ''
, xmlParameters
, true
, eventRule.UserId
, true);
// KeSae : 21/04/2010 : Alerting multiple mail recipients
NVMPEventRuleRecipients::sendMail(eventRule.RuleId
, eventParameters.AlertTemplateId
, mappings
, xmlParameters);
}
else
throw error("@SYS94918");
When the email for this alert is sent, every user in the list will receive a link to the alert by email.
Download the xpo here
At a customer’s site, I was creating some extra AIF wcf services so that some extra tables would be externally available. For creating the WCF service, I was using the service wizard in Ax 2009 which is described here : http://msdn.microsoft.com/en-us/library/aa609947.aspx
The newly created service was deployed to the Internet Information Server but when the .Net application tried to reference the webservice, the following happened : The service was prompting for credentials and did not work properly.
After a certain amount of searching time and nearly giving up, I was browsing the configuration file of the web services directory and discovered that the BindingMethod of the deployed services was configured to use basicHttpBinding.
This was the actual problem because the wsdl looked like this : (negotiate authentication tags were added, …)

Changing the binding method to wsHttpBinding creates the service without the negotiateAuthentication and takes care of our annoying credential problem.
