Friday 20 January 2017

File upload and download in AX 7

FormLook

When you click the Upload button, a dialog opens where you can pick a file on your computer and upload it. It even shows progress of uploading.
Uploading

The whole upload is triggered by a single statement: File::GetFileFromUser(). You don’t have to deal with any details.
By default, the file is uploaded to a temporary blob storage and can be accessed through some ugly URL such as this:
If you click the download button, it will navigate to the URL and your browser will do the rest:
SaveFile
Code of Download button is again a one-liner: new Browser().navigate(fileUrl).
This is the complete code of the form, showing also how to get the URL of the uploaded file:

[Form]
public class UploadDownloadForm extends FormRun
{
    str fileUrl;
 
    [Control("Button")]
    class UploadButton
    {
        public void clicked()
        {
            FileUploadTemporaryStorageResult result = File::GetFileFromUser() as FileUploadTemporaryStorageResult;
            if (result && result.getUploadStatus())
            {
                fileUrl = result.getDownloadUrl();
                info(fileUrl);
            }
        }
    }
 
    [Control("Button")]
    class DownloadButton
    {
        public void clicked()
        {
            new Browser().navigate(fileUrl);
        }
    }
}

Your files typically aren’t accessible by URL, because they’re in database or in a secured storage. But that’s not a problem. Just load the content of your file to a stream and pass it to File::SendFileToUser(). It will put the file to the temporary blob storage and navigate to the URL, therefore users can download the file in the same way as above.

Thursday 22 December 2016

How to Create AX 7 tile

How to Create AX 7 tile


Tile is a new element in form design in latest version of Dynamics AX. As with tiles at other places in Microsoft products, it is used to provide key information on dashboard with or without graphical image. Tile also have drill down functionality to go to an item which have detailed information about the topic.

In this walkthrough, I’ll create a simple counting tile which displays the number of record in a table.
As a pre-requisite, I have a simple table ‘SONTable2’ with two string fields – ID and Description.





Firstly, create a query based upon this table. I have set the Dynamics field property to ‘Yes’.

Secondly, create a new form which displays the record of this table in the grid. This can be a normal form which is used upon drill-down. I have used the same query as data source to this form.


Here is how this form looks like in UI



Make sure there is some data in the table/form, in order to generate valid count in tile.

Third step, create a display menu item for this form. Key point is to mention query property in this menu item to the query already created for tile.

 
 
Fourth step, create a new tile. Mention the label, name of display menu item (created above), menu item type and ‘Type’ property to ‘Count’. Leave ‘Query’ property blank.
 
 
Lastly, create a form which will hold this tile. Create a new ‘Tile button’ and point to the tile.
 
To open this form, you may create other menu item, add it to menu etc. I am just setting this form as ‘Startup object’ in VS to open it. And below is the result.


Clicking on the tile will take me to the ‘SonForm’ form; which shows the four records.
I hope that this simple walkthrough will enable you to try this new form element and implement more complex scenarios. Do post your feedback/questions in comments below.

Thursday 23 June 2016

Axutil Commands

Axutil Commands

* AOS name in Server Configuration
Models List:
axutil list /config: <AOS name>
Model elements :
axutil view /model:<model id> /config:<AOS name>


Create a model:
axutil create /model:<model name> /layer:<layer name> /config:<AOS name>
Delete the existing model :

axutil delete /model:<model id> /config:<AOS name>
 export the modelstore:
axutil exportstore /file:”specify the location” /config:<AOS name>
Import a modelstore:
axutil importstore /file:”specify the location” /config:<AOS name>
 Edit a model properties:
Axutil edit /model:”model id” /manifest:Version=”<to which version>”,Publisher=”<publisher name>”,Description=”<Description>”
export the model:
axutil export /model:<model id> /file:”specify the location” /config:<AOS name>
 Import a model:
A model can be imported using several options which can be defined in the Axutil Command
Simple import of a model:
axutil import /file:”specify the location” /config:<AOS name>
Import with Conflict overwrite option:
axutil import /file:”specify the location” /config:<AOS name> /conflict:overwrite
Import with Conflict push option ( only for developers and technical consultants):
axutil import /file:”specify the location” /config:<AOS name> /conflict:push
Import with conflict overwrite and also use replace keyword:
axutil import /file:”specify the location” /config:<AOS name> /conflict:overwrite /replace:”model name”

Tuesday 17 November 2015

Testing Read service in X++

static void TestingService(Args _args)
{
    PurchPurchReqService     customerService;            // Customer Service class
    CustCustomer            customer;                   // Customer Document object
    PurchPurchReq            customerRead;               // Customer Document object
    CustCustomer_CustTable  custTable;                  // CustTable data object
    CustCustomer_CustTable  custTableRead;              // CustTable data object
    AifEntityKeyList        entityKeyList;              // Entity key list
    AifEntityKeyList        entityKeyListFind;          // Entity key list
    AifQueryCriteria        queryCriteria;
    AifCriteriaElement      criteriaElement;
    AccountNum              accountNum;




    // Create the service instance
    customerService =  PurchPurchReqService::construct();


    queryCriteria = new AifQueryCriteria();
    criteriaElement = AifCriteriaElement::newCriteriaElement('VendPurchOrderJour', 'PurchId', AifCriteriaOperator::Equal, 'US1PO0000440');
    queryCriteria.addCriteriaElement(criteriaElement);
    entityKeyListFind = customerService.findKeys(queryCriteria);


    // Read Customer using returned entity key
    customerRead = customerService.read(entityKeyListFind);
    info(customerRead.serialize());
    //custTableRead = customerRead.parmCustTable().get_Item(0);
    //info(strfmt("Read customer: Account Number: %1, Name: %2.", custTableRead.parmAccountNum(), custTableRead.parmName()));





}

Debugging Services in AX 2012

Regardless of the adapter type you choose, services in AX 2012 run as IL code - even if you are using the file adapter.  To debug IL code
you must use Visual Studio.
The steps for debugging a service are:
  1. On the AOS, install the AX Application Explorer from the Microsoft Dynamics AX CD by choosing the
    component Developer Tools, and then click Visual Studio Tools.  If the AX debugger is not installed,
    you will also need to install it.
  2. Open Visual Studio, create a new project, and in the AX Application Explorer find the methods in the
    service classes that are of interest.
  3. In Visual Studio add breakpoints where needed.
  4. Click Debug, and then click Attach to Process.
  5. Mark the checkboxes for Show processes from all users and Show processes in all sessions.
  6. Select AX32Serv.exe and click Attach.The Ax32Serv.exe won't be able available if you are not debugging on the AOS, so
    you need to be on the AOS.
  7. In a separate instance of VS (so have two different projects/solutions open) run the code that calls
    the service.One instance to run the code that
    calls the service and another instance of VS to do the debugging.  By
    having two instances open, you can leave the debugging instance attached to the
    AOS while you run the service code over and over again.

Friday 13 November 2015

AIF Document services operations

static void AifSample_CustomerService(Args _args)
{

CustCustomerService     customerService;            // Customer Service class
    CustCustomer            customer;                   // Customer Document object
    CustCustomer            customerRead;               // Customer Document object
    CustCustomer_CustTable  custTable;                  // CustTable data object
    CustCustomer_CustTable  custTableRead;              // CustTable data object
    AifEntityKeyList        entityKeyList;              // Entity key list
    AifEntityKeyList        entityKeyListFind;          // Entity key list
    AifQueryCriteria        queryCriteria;
    AifCriteriaElement      criteriaElement;
    AccountNum              accountNum;
    Name                    name;
    ;

    // Create the service instance
    customerService =  CustCustomerService::construct();

    // Create the Customer document object
    customer = new CustCustomer();
    customer.createCustTable();                            // Create the CustTable list
    custTable = customer.parmCustTable().addNew();         // Add CustTable instance to CustTable list

    // Initialize the CustTable instance
   // custTable.parmName("Cust01");
    custTable.parmAccountNum("22220002");
    custTable.parmCustGroup("10");
    custTable.parmCurrency("USD");
    custTable.parmPartyType(DirPartyType::Organization);

    // Create Customer
    entityKeyList = customerService.create(customer);
    accountNum = entityKeyList.getEntityKey(1).parmKeyDataMap().lookup(fieldnum(CustTable, accountnum));
    info(strfmt("Created customer:  Account Number: %1.", accountNum));

    //Creating another Customer
    entityKeyList = customerService.create(customer);
    accountNum = entityKeyList.getEntityKey(2).parmKeyDataMap().lookup(FieldNum(Custtable,accountNum));
    info(strfmt("Created another Customer :  Account Number : %1. ",accountNum));


    // Read Customer using returned entity key
    customerRead = customerService.read(entityKeyList);
    custTableRead = customerRead.parmCustTable().get_Item(0);
    info(strfmt("Read customer: Account Number: %1, Name: %2.", custTableRead.parmAccountNum(), custTableRead.parmName()));

    // Update Customer
    custTableRead.parmName(custTableRead.parmName() + ": Updated Name");
    customerService.update(entityKeyList, customerRead);
    info (strfmt("Updated Customer: Account Number: %1.", custTableRead.parmAccountNum()));

    // Call Read to check update
    customer = customerService.read(entityKeyList);
    custTable = customerRead.parmCustTable().get_Item(0);
    info(strfmt("Read updated customer: Account Number: %1, Name: %2.", custTable.parmAccountNum(), custTable.parmName()));

    // Call FindKeys to find entity keys of matching customer entity keys
    queryCriteria = new AifQueryCriteria();
    criteriaElement = AifCriteriaElement::newCriteriaElement('CustTable', 'CustGroup', AifCriteriaOperator::Equal, '10');
    queryCriteria.addCriteriaElement(criteriaElement);
    entityKeyListFind = customerService.findKeys(queryCriteria);
    info(strfmt("Find customer keys: Result count: %1", entityKeyListFind.getEntityKeyCount()));

    // Call Find to find matching customers
    queryCriteria = new AifQueryCriteria();
    criteriaElement = AifCriteriaElement::newCriteriaElement('CustTable', 'CustGroup', AifCriteriaOperator::Equal, '10');
    queryCriteria.addCriteriaElement(criteriaElement);
    customerRead = customerService.find(queryCriteria);
    info(strfmt("Find customer: Result count: %1", customerRead.existsCustTable()?customerRead.parmCustTable().get_Count():0));

    info("TO DO: To test delete, uncomment delete code in the job.");
    // TODO: UNCOMMENT TO DELETE CUSTOMER
    /*
    // calling deleting customer
    customerService.delete(entityKeyList);
    info(strfmt("Deleted customer:  Account Number: %1.", accountNum));
    */
    pause;

}

Monday 13 October 2014

Create/Delete Customer using AIF Service Class in Dynamics AX

The Application Integration Framework allows us to create/update/delete or read data. Now in AX2009 we have a facility of creating/deleting records using AIF Service classes. There is "NO ADDITIONAL AIF SETUP"(Like Enabling Endpoints etc.) required to execute the code via service class. The services can be used to read/write data in AX.
X++ service class job is illustrated below. 

tatic void Services_CustTable_Create(Args _args)
{
    // Customer Service class
    CustCustomerService     custService;
    CustCustomer                customer;

    // Data object of Service class
    CustCustomer_CustTable  custTable;
    AifEntityKeyList               entityKeyList;
    AccountNum                    accountNum;
    ;

    //Service instance
    custService =  CustCustomerService::construct();

    customer = new CustCustomer();
    customer.createCustTable();
    custTable = customer.parmCustTable().addNew();

    custTable.parmName("Cust_Service");
    custTable.parmCustGroup("20");
    custTable.parmCurrency("EUR");
    custTable.parmPartyType(DirPartyType::Organization);

    // Create Customer
    entityKeyList = custService.create(customer);

    if(entityKeyList)
        accountNum = entityKeyList.getEntityKey(1).parmKeyDataMap().lookup(fieldnum(CustTable, AccountNum));
        infolog.messageWin().addLine(accountNum);
}

static void Services_CustTable_Delete(Args _args)
{
    AifEntityKeyList          entityKeyList;
    AifEntityKey               aifEntityKey;
   
    // Data object of Service class
    CustCustomerService     custService;
    CustTable                     custTable;
    ;

    aifEntityKey  = new AifEntityKey();
    entityKeyList = new AifEntityKeyList();
    custService   = CustCustomerService::construct();

    select firstonly custTable
        where custTable.Name == "Cust_Service";

    aifEntityKey.parmKeyDataMap(SysDictTable::getKeyData(custTable));
    entityKeyList.addEntityKey(aifEntityKey);

    try
    {
        // Delete Customer
        custService.delete(entityKeyList);
        info ("CustTable record was successfully deleted.");
    }
    catch(Exception::Error)
    {
        exceptionTextFallThrough();
    }
}

SO Creation:

static void Services_SO_Create(Args _args)
{
    // Sales Order Service class
    SalesSalesOrderService     salesService;
    SalesSalesOrder                salesOrder;

    // Data object of Service class
    SalesSalesOrder_SalesTable  salesTable;
    SalesSalesOrder_SalesLine    salesLine;
    AifEntityKeyList                   entityKeyList;

    SalesId                                salesId;
    ;

    //Service instance
    salesService =  SalesSalesOrderService::construct();

    salesOrder = new SalesSalesOrder();
    salesOrder.createSalesTable();
    salesTable = salesOrder.parmSalesTable().addNew();
    salesLine   = salesTable.createSalesLine().addNew();

    // Mandatory data filled for SalesTable
    salesTable.parmCustAccount("4000");
    salesTable.parmDeliveryDate(today());
    salesTable.parmPurchOrderFormNum(‘Test’);

    // Mandatory data filled
    salesLine.parmItemId(‘B-R14′);
    salesLine.parmSalesQty(1);
    salesLine.parmSalesUnit(‘Pcs’);

    // Create Sales Order
    entityKeyList = salesService.create(salesOrder);
    if(entityKeyList)
        salesId = entityKeyList.getEntityKey(1).parmKeyDataMap().lookup(fieldnum(SalesTable, SalesId));
        infolog.messageWin().addLine(salesId);
}