[AX]AX2012 AIF(三):创建自定义文档服务

在对文档服务编程模型了解之后,创建自定义的文档服务就显得相对简单了,基本步骤是:

  • 创建Query,以AxdXXX命名,加入一个表作为根Datasource,在其Datasource下可以加入子数据源,设置好表之间的relation。
  • 从开发Workspace的菜单Tools > Application Integration Framework > Create Document Service启动Wizard工具,或者直接在AOT中右键点击Query,选择Add-ins>AIF document service wizard。在Wizard工具中需要设置Document name、Service class name、Document object class name、Axd class name等信息,选择需要生成的标准文档服务操作,以及是否生成Ax<Table>类,完成后Wizard工具会给自动创建一个Project,工程下包含所需的文档服务类、数据对象类、Axd类、宏定义、Service AOT节点和一个用于生成文档XSD的Job。
  • 创建出入站端口部署文档服务。

试图编译自动创建的工程,你会得到一些错误和Todo消息,错误来自于Ax<Table>的cacheObject和cacheRecordRecord两个方法。打开这两个方法,你会发现函数函数中的代码都注释掉了,而函数声明中的CacheRecord是无效的。CacheObject用来缓存后续需要用到的对象,函数的名称根据需要重新命名,比如AxSalesLine的axSalesTable方法,它缓存一个axSalesTable类的实例,在其他方法中(比如AxSalesLine的setCustAccount)使用这个方法直接得到这个axSalesTable实例,如果需要这个函数把函数中的cacheObject替换成你的类名称并去掉注释。如果不需要缓存任何对象,直接删掉这个函数。cacheRecordRecord作用也是一样,只不过它用来缓存一条表记录,比如AxSalesLine的inventTableRecord方法,同样如果不需要就删掉好了。

在输出的Toto消息很多中除了很多关于设置Label和Description的提示外,有一些是值得关注的:

  • Axd类的prepareForSaveExtended()方法中有一条注释是“//TODO Put validating code for SalesPickTable here”,这是提示添加自定义的数据验证,比如检查重复的数据记录。MSDN讲重载prepareForSave()方法来加入自定义的验证,实际上AxdBase的prepareForSaveExtended()方法会调用prepareForSave方法,而我们的Axd类重载了prepareForSaveExtended方法,重载后不会再调用prepareForSave方法,所以MSDN的说法应该是有误,直接在Axd类的prepareForSaveExtended方法验证数据就好了。
  • Axd类的prepareForSaveExtended()方法还有一条注释是“//TODO: Add code here to ensure that required fields specified in the initMandatoryFieldsMap method are sent in by the service caller.”,这也是提示要对入站数据检查是否包含那些设定为强制的字段数据。initMandatoryFieldsMap()是AxdBase的一个方法,它默认添加DirPartyPostalAddressView的一些字段为强制,在你的Axd类中如果需要添加其他的一些未在Ax<Table>类中设为强制的字段或者parm方法,可以这样来使用:
protected void initMandatoryFieldsMap()
{
    super();  
    this.setParmMethodAsMandatory(
        classnum(AxdSalesOrder),
        methodstr(AxdBase,parmDocPurpose));
    this.setParmMethodAsMandatory(
        classnum(AxSalesLine),
      methodstr(AxSalesLine,parmSalesQty));
    this.setTableFieldAsMandatory(
        tablenum(SalesLine),
        fieldstr(SalesLine,SalesUnit));
}

AxdBase.setParmMethodAsMandatory()设置Axd类的某个parmXXX方法为强制,AxdBase.setTableFieldAsMandatory()则是设置表的某个字段为强制。

  • 另外一些Todo是在Axd类的getConstraintList()方法,包括验证表、设置constraint type、constraint id。这个方法添加一些AifConstraint()的实例到AifConstraintList列表,注释说明是for internal use的,没有找到更多有用的信息来判断这个Constraint列表的具体作用。AxdCustomer的GetConstraintList()是这样的:
public void getConstraintList(Common _curRec, AifConstraintList _constraintList)
{
    AifConstraint   aifConstraint = new AifConstraint();
    CustTable       custTable;
    ;
    if (_curRec.TableId != tablenum(CustTable))
    {
         throw error(strfmt("@SYS23396",funcname()));
    }
    custTable = _curRec ;
    aifConstraint.parmType(AifConstraintType::Customer);
    aifConstraint.parmId(custTable.AccountNum);
    _constraintList.addConstraint(aifConstraint) ;
}

这里用到的AifConstraintType枚举类型包含NotSet、Customer、Vendor、NoConstraint、Warehouse,既然不知道它的具体作用,不妨保持原有代码,即添加一个AIFConstraintType::NoConstraint的对象到列表。

除了以上自动创建代码中的问题,在创建自定义文档服务MSDN还提示需要注意的一些问题:

  • 在出站调用中,Axd类的initQueryFromEntityKey()方法会被调用,它从对象键值构建一个数据库查询,比如AxdPurchaseRequisition,我们需要额外检查采购订单是否已经被关闭,所以在AxdPurchaseRequisition.initQueryFromEntityKey()方法中有对应的订单状态检查。
  • Ax<Table>默认不会验证数据,需要调用Ax<Table>.validateInput(true)启用数据验证。
  • 如果文档数据中有引用到DocuRef表,建议是只使用文本格式的Note类型以防止数据中包含恶意代码,可以调用AxDocuRef类来验证附属文档类型。
  • 对于入站文档不建议直接生成业务交易,除非来源确信可靠,否则最好是先生成Journal,手工过账后生成正式的交易记录,以避免来历不明的文档在系统中生成不正确的信息。

更多内容参见http://msdn.microsoft.com/en-us/library/aa856656.aspx

原文地址:https://www.cnblogs.com/duanshuiliu/p/2886413.html