Tuesday, April 23, 2019

D365FO table browser object reference not set to an instance of an object

Meanwhile your development you may face the error 'Object reference not set to an instance of an object' in Visual Studio while opening table browser. Follow the following steps to get rid of this error.

  1. Build the custom model with database synchronization checked.
  2. Reset IIS.
  3. Refresh AOT.
Several other blogs have suggested to do only step 1, which is not sufficient. Doing step 2 and 3 will definitely resolves the issue as it did in my case.   

Thursday, April 11, 2019

D365FO get workflow comment (submission, rejection, approval or any comment) X++

You can get workflow comment at any stage, be it from submission, approval, rejection or any other stage. There will be only one query for all of them with only change of an Enum WorkflowTrackingType value highlighed in the query below.

In this method , for example, the rejected comment of Purchase order workflow is fetched through query by filtering workflowTrackingTable.TrackingType with Rejection element of the enum.


private WorkflowComment getPORejectedWorkflowComment(PurchId _purchId)
{
        WorkflowTrackingTable           workflowTrackingTable;
        WorkflowTrackingStatusTable     workflowTrackingStatusTable;
        WorkflowTrackingCommentTable    workflowTrackingCommentTable;
        PurchTable                      purchTable;

        purchTable = PurchTable::find(_purchId);

        select ContextCompanyId, ContextTableId, ContextRecId from workflowTrackingStatusTable
        where workflowTrackingStatusTable.ContextCompanyId    == curext()
           && workflowTrackingStatusTable.ContextTableId      == purchTable.TableId
           && workflowTrackingStatusTable.ContextRecId        == purchTable.RecId
        join firstonly TrackingId, CreatedDateTime from workflowTrackingTable order by CreatedDateTime desc
            where workflowTrackingTable.WorkflowTrackingStatusTable == workflowTrackingStatusTable.RecId
                && workflowTrackingTable.TrackingType == WorkflowTrackingType::Rejection
        join Comment from workflowTrackingCommentTable
            where workflowTrackingCommentTable.WorkflowTrackingTable == workflowTrackingTable.RecId;

        return workflowTrackingCommentTable.Comment;
    }

The enum WorkflowTranckingType has following elements, specifying which you can get the specific comment:






Wednesday, April 10, 2019

D365FO turn off maintenance mode

You may face some problem like batch management service is not starting. It is because the maintenance mode is enabled. You have to run the following command on VM to disable maintenance mode. Run CMD as administrator and execute following command:

C:\AosService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe --metadatadir C:\AosService\PackagesLocalDirectory --bindir C:\AosService\PackagesLocalDirectory\Bin --sqlserver . --sqldatabase axdb --sqluser axdbadmin --sqlpwd AOSWebSite@123 --setupmode maintenancemode --isinmaintenancemode false

In the previous command the AOS is installed in 'C' drive, the database administrator user is 'axdbadmin' and its password is the default password of axdbadmin 'AOSWebSite@123'.

Tuesday, April 9, 2019

Microsoft One Version, D365FO easy update

You need updated features of Microsoft D365FO for easy flow of your business processes. You may still be wavering whether to update your D365FO new version or not. This is very normal because you need see time, budget and relevant capability to do this; simply you can say,"The update is difficult." Thanks to Microsoft One Version which makes totally easy. The One Version is the update service that Microsoft itself runs on partners and customers environment. Microsoft does so to keep all environments consistent, up to date, seamless and error free. To feel not being forced to always update like we experienced on Windows 10, customers and partner can pause automatic update in this case; and even can control features in deployment.

The 'easy' term is used due to effortless update w.r.t customers. The partner/ customer receives notification for the update time scheduled on cloud environments and receives another when update is completed. The result log can be monitored in LCS. All the updated features will be available when update is done.

While it may look very fluent from outside, there are many process included to make this happen. They are as follows:

Regression Suite Automation Tool (RSAT):
It is a scripting tool. Specific to partner/customer organization environment the regression test script is run before update is processed on production.

Safe Deployment Rings (SDR):
The version and update process is taken step wise. Each update is first carried out internally on Microsoft environments, then to partner and finally on environments of customers. The process progresses to new step only when successfully completed. 

Release Validation Program (RVP):
For insuring successful general release which fits on every type of organization Microsoft uses RSAT suites provided by diverse partner/customer environments and run the regression script internally as part of SDR in addition to its own script.

Update time control:
Microsoft has given control to customer in case updates need to paused. You can find it Here on how it can be done.

Features control:
Customers can manage the features in their deployments. Deciding when the new feature shall be added and shall be adjustable to customer own business process.


The Microsoft One Version is undoubtedly an one of the biggest service related to updates. Making update a simpler and quite less threatening as it is managed by Microsoft through its many high quality processes and techniques. It relieves both the technical guy who carried out updates and customers by giving new feature control feature.


Thursday, April 4, 2019

D365FO get Vendor/Customer account from ledgerJournalTrans

You can get Vendor or Customer account from following ways:


1-  VendTable = VendTable::findByLedgerDimension(ledgerJournalTrans.LedgerDimension);

2- MainAccount MainAccount = MainAccount::findByLedgerDimension(LedgerDefaultAccountHelper::getDefaultAccountFromLedgerDimension(ledgerJournalTrans.LedgerDimension));

vendTable = VendTable::find(MainAccount.MainAccountId);

3- MainAccount MainAccount = LedgerDimensionFacade::getMainAccountFromLedgerDimension(ledgerJournalTrans.LedgerDimension);

vendTable = VendTable::find(MainAccount.MainAccountId);

D365FO Entity data populating from staging table to target table

Adding a custom field through extension in standard entity, you may encounter a problem where all fields are populated in staging table (including the custom field) but not in target table. The custom field will not make to be populated in main table after doing all necessary mapping. In this case you need to make post eventhandler of copyCustomStagingToTarget on entity.

In this example, a new field by name 'CustomField' on CustInvoiceLine table needs to be populated using FreeTestInvoiceEntity. The method execution will get 'CustomField' from staging table and update it in the target table.


/// <summary>
/// Populate custom field
/// </summary>
/// <param name="args"></param>
[PostHandlerFor(tableStr(FreeTextInvoiceEntity), tableStaticMethodStr(FreeTextInvoiceEntity, copyCustomStagingToTarget))]
 public static void FreeTextInvoiceEntity_Post_copyCustomStagingToTarget(XppPrePostArgs args)
 {
        DMFDefinitionGroupExecution                 _dmfDefinitionGroupExecution =  Args.getArg('_dmfDefinitionGroupExecution');
        FreeTextInvoiceStaging                      staging;
        CustInvoiceLine                             custInvoiceLine;
        CustInvoiceTable                            custInvoiceTable;
      
        custInvoiceLine.skipDataMethods(true);
        SelectableDataArea currentCompany = curExt();

        update_recordset custInvoiceLine setting
                CustomField = staging.CustomField
            join custInvoiceTable
                where custInvoiceTable.RecId == custInvoiceLine.ParentRecId
            join staging
                where staging.DefinitionGroup       == _dmfDefinitionGroupExecution.DefinitionGroup
                    && staging.ExecutionId              == _dmfDefinitionGroupExecution.ExecutionId
                    && staging.TransferStatus          == DMFTransferStatus::Completed
                    && staging.LineNumber             == custInvoiceLine.LineNum;
    }