AIF

AX 2012: Create AIF document service

Posted on Updated on

Purpose:

The purpose of this document is to illustrate how we can develop AIF document service, what are the important methods available that can be overridden to do the customization and finally how we can consume/unit test the document service through an external .NET application.

Business requirement:

Ability to integrate Dynamics AX with external systems.

Assumptions:

Application Integration Framework (AIF) has been configured to process inbound and outbound messages.

Development:

  • Create an AOT query. Prefix it with Axd to follow the naming convention for document service.
  • Run AIF document service wizard to generate/regenerate:
    • Document class (Axd class).
      • Represents whole business document.
      • Used to perform cross-table validations.
      • Serializes/deserializes the document to/from XML.
    • Document object class
      • Object interface to whole business document.
    • Data object classes
      • Object interface to underlying tables involved in the document.
    • AxBC classes, if chosen
      • Wrapper classes for underlying tables involved in the document.
      • Used to perform table-level validations.
        • For example, AxSalesLine.validateWrite method.
        • It then calls validateWrite method of SalesLine table.
      • Used by Axd class to create, read, update, delete data in tables.
    • Service class
      • Contains the service operations in the form of methods.
    • Service node
      • Exposes service operations to inbound/outbound ports
  • Change namespace property of service node (optional).
  • Generate incremental CIL.
  • Register the service
  • Create security privilege for each service operation (optional).
  • Create an enhanced inbound port
  • Choose an adapter
    • File system adapter
    • HTTP
    • ISABEL SEPA credit transfer
    • MSMQ
    • NetTcp
    • Windows Azure Service Bus
  • Choose service operations
  • Activate

Important methods:

  • Axd class
    • prepareForSave/prepareForSaveExtended method
      • Validation code goes here.
      • For example checkSalesTable method in AxdSalesOrder class.
    • updateNow method
      • Business logic to be executed post insert/update of document.
      • For example, post receipt in II7.
    • expandSurrogateForeignKeys method
      • To automatically resolve surrogate foreign keys to natural keys.
    • getSurrogateForeignKeyValue method
      • To manually resolve surrogate foreign keys to natural keys.
  • AxBC class
    • initMandatoryFieldsExemptionList method
      • To make a field optional which is mandatory at the table level.
    • initMandatoryFieldsMap method
      • To make a field mandatory which is optional at the table level.
    • set<Field> method
      • To set default value of a field in service.
      • This method calls parm method to set the default value.
      • For example, setLineNum method of AxSalesLine class.
      • It calls parmLineNum method of AxSalesLine class.

Consuming service:

  • Create console application in Visual Studio
  • Add service reference
  • Sometimes, setting some fields doesn’t work in C#. We use “<Field>Specified” parameters for them.
  • For example:
    • Course.Name = “Name”;
    • Course.NameSpecified = true;
    • Course.Description = “Desc”;
    • Course.DescriptionSpecified = true;

AX 2012: Create AIF custom service

Posted on Updated on

Purpose:

The purpose of this document is to illustrate how we can develop AIF custom service.

Business requirement:

Ability to integrate Dynamics AX with external systems.

Assumptions:

Application Integration Framework has been configured to process inbound and outbound messages.

Development:

  1. Create a data contract class.
    1. Use [DataContractAttribute(‘Name’)] attribute to indicate class represents data contract.
    2. Use [DataMemberAttribute(‘Name’)] attribute to indicate method represents data member.
    3. Use [AifCollectionTypeAttribute] attribute to define parameter and return types.
  2. Create a service class.
    1. Set RunOn property of class to Server.
    2. Create a method attributed with [SysEntryPointAttribute(true)] to designate it as a service operation.
    3. The boolean parameter of attribute defines whether AOSAuthorization property of tables will be checked or not in this method.
  3. Create a service contract by creating service node.
  4. Add service operation.
  5. Create a service group for the basic inbound port.
  6. Deploy the service group.
  7. The inbound port created must be activated now.

AX 2012: Trigger AIF Document Service Outbound Message in X++

Posted on Updated on

Purpose:

The purpose of this document is to illustrate how we can trigger the generation of AIF document service outbound message in X++.

Business requirement:

Ability to generate an AIF outbound xml message on demand.

Assumptions:

Outbound port is configured using file system adapter.

Development:

Please find the job below to trigger an AIF document service outbound message in X++. The job uses the standard CustCustomerService class to generate outbound xml for customer data. Likewise the code can be used for any other valid document service class.

// Developed on 18 Feb 2016 by Muhammad Anas Khan
// Blog: dynamicsaxinsight.wordpress.com
// LinkedIn: pk.linkedin.com/in/muhammadanaskhan
// Description: Trigger AIF document service outbound message
static void sendElectronically(
    XMLDocPurpose _xMLDocPurpose,
    AifSendMode   _aifSendMode = AifSendMode::Async)
{
    AxdSendContext    axdSendContext = AxdSendContext::construct();
    AifEntityKey      aifEntityKey = AifEntityKey::construct();
    AifConstraintList aifConstraintList = new AifConstraintList();
    AifConstraint     aifConstraint = new AifConstraint();
    CustTable         custTable;
    Map               keyData;
    
    custTable = CustTable::find("1101");
    
    keyData = SysDictTable::getKeyData(custTable);
    aifEntityKey.parmTableId(custTable.TableId);
    aifEntityKey.parmRecId(custTable.RecId);
    aifEntityKey.parmKeyDataMap(keyData);
    axdSendContext.parmXMLDocPurpose(_xMLDocPurpose);
    axdSendContext.parmSecurity(false);
    aifConstraint.parmType(AifConstraintType::NoConstraint);
    
    aifConstraintList.addConstraint(aifConstraint);
    AifSendService::submitDefault(
        classnum(CustCustomerService),  //Service class goes here
        aifEntityKey,
        aifConstraintList,
        _aifSendMode,
        axdSendContext.pack());
}

AX 2012: AIF Document Service Invalid Data Container Type

Posted on

Error:

Invalid data container type.

Resolution:

Compile forward AfStronglyTypedDataContainer class.

AX 2012: Integrate Dynamics AX with Website

Posted on Updated on

the-web-1

Challenge:

What if you need to integrate a Retail E-Commerce website with the powerful Dynamics AX ERP at backend to leverage numerous functional capabilities it offers in the areas like but not limited to Supply Chain Management. Then you are reading the right blog post! We can achieve it through exposing custom AIF services as web services on IIS using enhanced inbound ports via HTTP adapter. In this post, we’ll expose customers data in Dynamics AX 2012 persisted in CustTable to an external interface using web services.

To simplify things, we’ll create a read service operation and then test our custom AIF service exposed as a web service using .Net console application. Although this blog post uses C# consumer to consume the custom service but the same service can be consumed by any website development platforms like ASP.NET and the possibilities are limitless!

Prerequisites:

1. Full compile revealing no errors.
2. Full CIL revealing no errors.
3. Install web services on IIS.
4. Configure default AIF website created while performing step 3.

Development:

1. Create contract class MAKCustTableContract.

  • Declare class variables for chosen fields of CustTable. Use same EDTs as used by table fields.
  • Create parm methods for each of the class variables.
  • Some of the parm methods are given below for reference.
  • To generate parm methods automatically, read this post.
[DataContractAttribute]
class MAKCustTableContract
{
    CustAccount accountNum;
    CustBankAccountId bankAccount;
    CustCreditMaxMST creditMax;
    CustCreditRating creditRating;
    CustCurrencyCode currency;
    CustGroupId custGroup;
    CustDlvModeId dlvMode;
    DlvReasonId dlvReason;
    CustInvoiceAccount invoiceAccount;
    VendAccount vendAccount;
}
[DataMemberAttribute('AccountNum')]
public CustAccount parmAccountNum(CustAccount _accountNum = accountNum)
{
    accountNum = _accountNum;

    return accountNum;
}

[DataMemberAttribute('BankAccount')]
public CustBankAccountId parmBankAccount(CustBankAccountId _bankAccount = bankAccount)
{
    bankAccount = _bankAccount;

    return bankAccount;
}

3. Create service class MAKCustTableService.

  • Add readCustTable() method.
class MAKCustTableService
{
}
[
    SysEntryPointAttribute(true),
    AifCollectionTypeAttribute('return',Types::Class,classStr(MAKCustTableContract))
]
public List readCustTable()
{
    MAKCustTableContract    contract;
    List                    custlist = new List(Types::Class);
    CustTable               custTable;

    while select custTable
        where custTable.CustGroup == '20'
    {
        contract = new MAKCustTableContract();
        contract.parmAccountNum(custTable.AccountNum);
        contract.parmBankAccount(custTable.BankAccount);
        contract.parmCreditMax(custTable.CreditMax);
        contract.parmCreditRating(custTable.CreditRating);
        contract.parmCurrency(custTable.Currency);
        contract.parmCustGroup(custTable.CustGroup);
        contract.parmDlvMode(custTable.DlvMode);
        contract.parmDlvReason(custTable.DlvReason);
        contract.parmInvoiceAccount(custTable.InvoiceAccount);
        contract.parmVendAccount(custTable.VendAccount);
        
        custlist.addEnd(contract);
    }

    return custList;
}

4. Create new service MAKCustTableService.

  • Create a new service node under AOT > Services.

Untitled

  • Expand service node just created.
  • Right click on Operations to add new service operation and select the class method readCustTable.

Untitled

  • Right click MAKCustTableService > Add-Ins > Register service.
  • Make sure it shows NoError in the status.

Untitled

4. Create enhanced inbound port MAKCustTableServices.

  • Open Functional workspace.
  • Click System administration>Setup>Services and Application Integration Framework>Inbound ports.
  • Click New to create new inbound port.
  • Select HTTP for the adapter.
  • Select default AIF website in the URI.

Untitled

  • Select Service operations from the Service contract customizations fast tab.

Untitled

  • Activate the enhanced inbound port.

Untitled

5. Test the URI address of the enhanced inbound port in the browser to ensure the service is activated.

Untitled

5. Test the AIF custom service with C# consumer in .Net console application.

  • Open Visual Studio 2010.
  • Create new .Net console application project in C#.
  • Add new Service reference in the project Service References.
  • Give the URI of the enhanced inbound port we created in address.

Untitled

  • Give the Program definition as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MAKServiceConsumer
{
    using MAKCustTableServices;

    class Program
    {
        static void Main(string[] args)
        {
            CallContext context;
            MAKCustTableServiceClient client;
            List list;

            context = new CallContext();
            context.Company = "CEU";

            client = new MAKCustTableServiceClient();
            list = client.readCustTable(context).ToList();
        }
    }
}
  • Debug the program to see the web service returning data 🙂

Untitled

AX 2012: Creating enhanced inbound port

Posted on Updated on

Prerequisites:

1. Full compile has been performed revealing no errors
2. Full CIL has been performed successfully
3. Incremental CIL has been performed after compiling the new service class


To create an enhanced inbound port for your custom service, please follow the steps below:

1. Right click on the service node, CustomerService in this case, and click Add-Ins > Register service
2. This opens AIF services dialog where you can search for your newly created service port in the list
3. Open Application workspace and navigate to:

  • System Administration > Setup > Services and Application Integration Framework > Inbound ports

4. Click New button
5. Give name and description of the port. In this case CustomerServices

Untitled

6. Click Service operations

Untitled

7. Move your service operations towards left pane
8. Click Activate

Untitled