Quantcast
Channel: AX Code | Stoneridge Software
Viewing all 71 articles
Browse latest View live

X++ Select Statements That Look More Like SQL

$
0
0

As I’ve progressed as an AX developer, I’ve had to lean on many of the skills that I had from a former job as a C# developer where I used a lot of SQL queries. Working with data in X++ is similar until you try to write it like it would be written in SQL.

I would like to explain a quick tip that I got when working with multiple joins recently in X++,  as well as some other best practices when working with data.

Working with vendTrans and ProjTable, I needed to join a few tables to get to the data that I needed.  As I stated above, I came from a very SQL query heavy development environment, so my first step when working with data like this is to write it in SQL.

 

SQL Statement:

select p.Name, p.Workerresponsible, p.custAccount, v.ProjId, vit.*,
	from PSAPwpInvoiceTransView as v
        	inner join VendInvoiceTrans as vit
			on vit.RecId = v.VendInvoiceTransRecId
		inner join VendTrans as vt
			on vit.InvoiceId = vt.invoice
		inner join ProjTable as p
			on p.ProjId = v.projId
        where vt.voucher = '#########'

First X++ select:

select vendTrans
            join vendInvoiceTrans
            join ProjId from  view
            join Name, WorkerResponsible, CustAccount from projTable
                where projTable.ProjId ==view.ProjId
		   && vendTrans.voucher == '#########'
		   && vendInvoiceTrans.InvoiceId == vendTrans.invoice
		   && vendInvoiceTrans.RecId == view.VendInvoiceTransRecId

As you can see above, I have all of the same joins and fields selected. There are definite differences in the languages that you cannot get around, but the tip that I received allows you to better see and understand were your joins are and where you might have an issue.

Easier to read X++:

select firstonly vendTrans
            where vendTrans.voucher == '#########'
        exists join vendInvoiceTrans
            where vendInvoiceTrans.InvoiceId == vendTrans.invoice
        exists join view
            where vendInvoiceTrans.RecId == view.VendInvoiceTransRecId
        exists join projTable
            where projTable.ProjId ==view.ProjId

 

More X++ Select Statement Tips:

1. Place the where clauses for each join under the line adding the join and table.

This gives you a better view of which fields are being joined, and helps with debugging if you have issues. This also give you a more “SQL-Like” visual of the select statement.

2. Make sure that you are using the correct joins. 

As seen above, I had inner joins on all of the tables and was selecting fields that I thought I needed.  After some testing, I realized the best practice is using Exists Joins, as then I did not need the fields from the joining tables and I only needed to make sure they existed in the table.  This speeds up the select as well as returns only the data that you need from VentTrans.

3. Use field groups to select ONLY the values that you need. 

As seen in the first X++ select that I wrote, I added a few of the fields that I needed from each table. Example:

join Name, WorkerResponsible, CustAccount from projTable

This will return only the fields stated, whereas without calling them out you would get all fields from the projTable.

4. First only and First fast. 

In the second select code block, I added the firstOnly directive.  This directive speeds up the data retrieval by getting the first record that it needs. FirstFast was not a great solution to this as it may still incur overhead setting up the cursor to support additional results.  Therefore, if you know there is only a single row, use First only.


Using the new Chain of Command feature in X++

$
0
0

Recently a new feature for X++ developers was announced by Michael Fruergaard Pontoppidan (MFP) called Chain of Command. I knew I would want to try it out as soon as I had some time and it is pretty slick. This post will show it in action with a simple example in Microsoft Dynamics 365 Enterprise edition (AX7).

Syntax Requirements

My example is nothing flashy. It shows how to raise an Infolog message when a sales line is added to a sales order and the customer does not have a credit rating. Since I know that when you add a sales line, the SalesLineType class is called and the insert method is used. My plan was to create an extension for the SalesLineType class and put custom code in the insert method. Here is the code for the new extension class:

[ExtensionOf(classStr(SalesLineType))]
final class SalesLineType_Extension
{
    public void insert(boolean dropInvent, boolean findMarkup, Common childBuffer, boolean _skipCreditLimitCheck)
    {
        CustTable   custTable;

        //get customer for evalation of credit rating
        custTable = CustTable::find(salesLine.CustAccount);

        if(!custTable.CreditRating)
        {
            info("Customer on sales line has no credit rating!");
        }

        // must call next when using Chain of Command pattern
        next insert(dropInvent, findMarkup, childBuffer, _skipCreditLimitCheck);
    }

}

 

Note the usage of the ExtensionOf attribute and the requirement to use the next keyword. The compiler told me to mark the class final so I did that also. Since the insert method in the SalesLineType class is public, I also had to use public in the extension class.
For reference, here is my project which is based on a new package in Visual Studio:

Project in visual studio

Here is the Infolog when saving a new sales line:

Infolog of a new sales line

Debugging Tip

One issue I ran into was around debugging with Visual Studio. The symbols would not load for my breakpoints. To resolve this, I marked the below setting in the Visual Studio debugging options. In addition to this one, there is also a similar setting in the Dynamics 365 node.

Debugging in visual studio

Chain of Command was released with Platform Update 9. You can find more information in this “What’s New or Changed in Dynamics 365 for Finance and Operations” article.

 

Working With Kernel Based Classes and AOT Based Tables in Dynamics AX

$
0
0

Thinking in the Abstract

If you have seen some of my blog articles before, you may have noticed that I look at automating documentation from time to time. This article will expand on the concept a bit, and use different components of Dynamics AX to accomplish or demonstrate some of the more abstract ways to retrieve information.

In the past, I have used TreeNode (https://msdn.microsoft.com/en-us/library/gg958198.aspx) to work with AOT-based objects. However, if working with just tables and fields, a lot of information can be retrieved by using some kernel based classes. I will demonstrate a couple here.

The first kernel based class is the DictTable class (https://msdn.microsoft.com/en-us/library/dicttable.aspx). DictTable allows you to retrieve information specific to a table. To use the object, the X++ code will resemble the following:

DictTable dictTable;
TableId tableId = tableNum(CustTable);

dictTable = new dictTable(tableId);

 

At this point, the dictTable object is instantiated and will be referencing the data for the CustTable table. Information about the table can be retrieved via method calls from the object. The DictTable documentation in the link above provides an example of retrieving and displaying some of the information on the table.

The next kernel based class is the dictField class (https://msdn.microsoft.com/en-us/library/dictfield.aspx). DictField is used to retrieve field information from a table. More on this in a moment, as I want to bring in another kernel based object before we start working with DictField.

The next kernel based object I want to bring in is the SQLDictionary table (https://msdn.microsoft.com/en-us/library/sqldictionary.aspx). This table describes the current state of the database with respect to the table and field metadata. For the purposes of our discussion, we need to work with two fields, tabId and fieldId. The tabId column is used to denote fields that exist in a specific table. FieldId is the field number of the field within the specific table. IF the fieldId value is 0, it is the ‘header’ record for the table, and it does not represent an actual field in the table.

NOTE: Do NOT go in and start randomly changing information in the SQLDictionary table. This will cause many issues within the system.

So, why do I bring this up? Well, using SQLDictionary in combination with DictField, you can work in the abstract with table information.

Here is an example:

// define a specific table Id, use the CustTable table in the demonstration
TableId tableId = tableNum(CustTable);
FieldId fieldId;

SqlDictionary sqlDictionary;
DictTable dictTable;
DictField dictField;

while select sqlDictionary
    where sqlDictionary.tabId == tableId
    && sqlDictionary.fieldId != 0
{
    dictField = new DictField(tableId,sqlDictionary.fieldId);

    info(strFmt("Name: %1, Label: %4, Label Id: %3, Base Type: %2", dictField.name(),dictField.baseType(),dictField.labelDefined(),dictField.label()));
}

 

The above code, when placed in a job, will list out all the fields in the table, the name, the base type (string, int, real, etc.), IF the field has a label defined on it, the label Id will be displayed, and the actual label text for this field. By looking at the documentation page for DictField, you can see what information you can retrieve from the method calls.

Also, using these objects, you can work abstractly, and actually work with data in the tables. Here is an example:

static void AbstractionDemoJob(Args _args)
{
    #define.AccountNum("ACCOUNTNUM")

    // define a specific table Id, use the CustTable table in the demonstration
    TableId tableId = tableNum(CustTable);
    FieldId fieldId;
    Common buffer;

    SqlDictionary sqlDictionary;
    DictTable dictTable;
    DictField dictField;

    dictTable = new dictTable(tableId);


    select firstOnly sqlDictionary
        where sqlDictionary.tabId == tableId
        && sqlDictionary.fieldId != 0
        && sqlDictionary.name == #AccountNum;

    if (sqlDictionary)
    {
        fieldId = sqlDictionary.fieldId;
        buffer = dictTable.makeRecord();
        buffer.(fieldId) = "BillTest";
        buffer.insert();

    }
}

 

Notice the code in the if statement. IF we get a SQLDictionary record for CustTable where there is a field named ACCOUNTNUM, we can use that information to fill in data. The above code gets the field Id from the SQLDictionary record, then it uses the common object and DictTable to create a table buffer based on CustTable. Then it sets the AccountNum field to BillTest, and finally inserts the record into the table.

Also, please note that additional information can be retrieved by using the SysDictField object instead of DictField (https://msdn.microsoft.com/en-us/library/sysdictfield.aspx). This inherits from DictField, and expands on the functionality provided.

In summary, as I have stated before, knowing some of the kernel based classes provides some rather unique tools for many different purposes. I hope I have provided some basis for thinking outside of the box on using Dynamics AX based objects.

Project Committed Cost Not Updating After Changes to PO in Dynamics AX

$
0
0

If you are running Dynamics AX 2012 and are doing work within the Project module you might have noticed an issue around committed costs on projects. In this example, we are looking at how committed costs work with Purchase Orders in Dynamics AX.

I’m going to assume you have a project setup along with a vendor. This scenario goes something like this.

  1. Create a PO and assign a project to it.
  2. Add a line to the PO
  3. Confirm the PO
  4. Go check your Committed Cost on the project and notice that everything is great
  5. You realize you made a mistake on the PO line so you go open the PO make your change and reconfirm
  6. You check your Committed Cost and realize that something isn’t right.

To fix this, there is a small code change that can be made to make sure that issue doesn’t happen again.

If you look at the ProjectCommitmentFacade class, in the doUpdateProjectCommitments method you will see that after a delete happens, the table buffer never gets cleared.

Simply, what you need to add is the following line to a couple places:
costControlTransComittedCostCheck.clear();

As an example:

if (!projectCommitmentsMap.exists(key))
{
//Relieve existing project commitment
        costControlPostingSourceDocumentLine =  CostControlPostingSourceDocumentLine::construct(
        		_sourceDocumentLineItem,
                costControlTransCommittedCost.ProjTransId,
                costControlTransCommittedCost.ProjId,
                costControlTransCommittedCost.CategoryId,
                costControlTransCommittedCost.ActivityNumber,
                costControlTransCommittedCost.LedgerDimension,
                0,
               	costControlTransCommittedCost.CurrencyCode,
                0,
                0,
                0);
          costControlPostingSourceDocumentLine.parmSupressMessages(_supressMessages);
          costControlPostingSourceDocumentLine.run(ProjCommittedCostUpdateAction::Delete);
          costControlTransCommittedCostCheck.clear();
}

 

With this simple change, your committed costs will now be correct, no matter what change you make on the PO.

How to Use the modelutil.exe to Delete a Model Name in Dynamics 365 for Operations

$
0
0

While getting introduced to development in Dynamics 365 for Finance and Operations, I found myself in a situation of adding/removing a model. There is a helpful tool we can use called “modleutil.exe”. This executable can be levied to accomplish a multitude of possibilities such as, import, delete, replace, and export.

In order to use the modelutil.exe to delete a model name, you first need to know where the modelutil.exe is located. Navigate to the AOSService folder, drill down in the PackagesLocalDirectory and its bin folder. The modelutil.exe is best used in a shell, which is a program that allows a command-based interface to the system’s kernel. Use CMD.exe or PowerShell.exe.

Working in the solution, I came across an issue that resulted in a harsh lesson. I made a model that I later did not need, only to find that the name was taken when I wanted to create a new model. For this instance, I created a model named Model1. I could not reuse the name Model1. Because modelutil.exe was not fully understood, I dug into the file structure. I recommend that you should not do that.

When using the modelutil.exe, you must understand some details. First, the exe requires you to use a command line tool, like command prompt. In a command line tool run the “modelutil.exe /?” this will display the following text.

ModelUtil.exe
Usage: ModelUtil.exe -export -metadatastorepath=[path to metadata store] -modelname=[name of the model to export] -outputpath=[path to the folder where the model should be saved]

Usage: ModelUtil.exe -import -metadatastorepath=[path to metadata store where model should be imported] -file=[full path to the file to be imported]

Usage: ModelUtil.exe -replace -metadatastorepath=[path to metadata store where model should be imported] -file=[full path to the file to be imported]

Usage: ModelUtil.exe -delete -metadatastorepath=[path to metadata store] -modelname=[name of the model to delete]

Usage: ModelUtil.exe -importxref -file=[path of xref file to import] -server=[sql server] -database=[database name]

If you notice, there are five different options to choose from: export, import, replace, delete, and importxref. Each of those options has further requirements. For the metadatastorepath, you will need the path to the PackagesLocalDirectory. For the modelname, you’ll need the model’s name.

The case that I described above will require the fourth option, the ‘-delete’ option. Once I deleted the previous model, I was able to continue to create a new Model1 model in Visual Studio.

 

Creating a List Panel for a Field Lookup in Dynamics AX

$
0
0

I recently had a scenario where we had to create a new vendor attribute that could have one or more values assigned to a vendor. The requirement wanted a drop-down field that opened a form and showed which values had been selected and which ones are still available. The lookup form should also allow the user to add/remove values. I was able to use an extension of the SysListPanel to accomplish this. I referenced form SysUserGroupInfo (Sys admin > Users > User groups). There are also list panels specific for financial dimensions. Form DimensionFocus (General ledger > Chart of accounts > Dimensions > Financial dimension sets) is an example. Here’s how you would go about creating a list panel for a field lookup in Dynamics AX.

Prerequisites

  • EDT created for the new attribute field
  • New table created to store the new attribute values and relation to the parent. For example, VendAccount if this is a new attribute for vendors. In this example, the new table has tow fields – VendAccount and CombinedCode.
  • The new field is added to the ‘parent’ form. Example VendTable if the new field is an attribute of a vendor. In my scenario, I also added the table in #2 as a datasource of the form.
  • New table created to store the new attribute values that are available. Similar to VendGroup. This table should be set to the Form Help of the new EDT in #1. This is like a setup form that will store categories that can be assigned to the vendor.

First, we need to create a form that will be used as the lookup form. This will be what is displayed when the drop down of the field is clicked.

Lookup form:

1. I used the Custom patter type since this form really won’t have any grids, action pain, etc. I set the Style property to Lookup and set the Show Delete / New Button to No. These properties are on the Design.

Creating a list panel for a field lookup

 

Creating a list panel for a field lookup

2. I set the auto declaration of the tab page control to Yes.

3. Add a datasource. This will be the new table that is created to store the new attribute values.
There is very little coding needed for this. You need to override the Init and close methods of the form and I created a Validate method. You will need to override the Active method of the datasource as well.

There is very little coding needed for this.  You need to override the Init and close methods of the form and I created a Validate method.  You will need to override the Active method of the datasource as well.

Override the init method of form

1. In the init method is where you initialize the SysListPanel. I used the SysListPanelRelationTableCallBack

public void init()
    {        
	 // create new panel that will show the selected and available categories
        sysListPanel = SysListPanelRelationTableCallback::newForm(element,
                             element.controlId(formControlStr(SSIVendCategoryValueTable, vendCategoryValue)),
                             "@SYS24159", "@SYS30545", 0, //#ImageUser,
                             tablenum(SSIVendCategoryValueTable),
                             fieldnum(SSIVendCategoryValueTable, CombinedCode),
                             fieldnum(SSIVendCategoryValueTable, CombinedCode),
                             tablenum(SSICategoryValueTable),
                             fieldnum(SSICategoryValueTable, DeptCatCode),
                             [fieldnum(SSICategoryValueTable, DeptCatCode), fieldNum(SSICategoryValueTable, DepartmentCategoryDesc)],
                             0, '',
                             identifierstr(Validate), '', '');
      
        super();

	 //set the record from the caller
        ssiVendCategoryValueTableRec = element.args().record();
        sysListPanel.init();		
    }

2. Details of SysListPanelRelationTableCallback::newForm()

  • The first few parameters are for the form and the form id.
  • Then you can set captions for the Selected and Available columns.
  • You can use an image for the form but I did not in this example.
  • Then you list the table that will be the source of the new data. In this example, it is called SSIVenCategoryValueTable.  This would be the table that is created in the prerequisites.  In my example, the relation and range field was the same.
  • After that, the ‘source’ table and fields are defined. This is the ‘parent’ relation.  The table that will be the source of the caller.  In my example, there is a relationship between the CombinedCode and DeptCatCode between the two tables.
  • After that, it is a container that will have the fields that will appear in the list panel. In my example, I have two.  The Code and Description.
  • In my example, I did not set the range field or value here. That is done in the Active method of the form datasource.
  • I did create a Validate method but did not create selectedMethod or availableMethod.

3. In the last part of the init method, I set the caller recId and then the init method of the list panel.

Override the close method of form

All that I put in the close method of the form is a call to the finalize method of the list panel. This will ensure all actions have been completed of the list panel to help ensure no errors occur when the form closes.

public void close()
    {
        sysListPanel.finalize();
        super();
 }

New validate method

I didn’t need any special validation for this solution. I just return a true value. This is similar to how the sysUserGroupInfo form does it.

boolean validate(userId _userId, AddRemove _addRemove, SysListPanelRelationTable _listViewHandler)
    {
        return true;
    }

Override the active method of datasource

This is where I added the ranges for the list panel and also where the call to fill the list panel happens. We need to make sure that we are only returning the new attribute values for the vendor that has been selected in the caller form.

[DataSource]
    class SSIVendCategoryValueTable
    {
        /// <summary>
        /// active method for datasource SSIVendCategoryValueTable
        /// </summary>
        /// <returns>
        /// int
	 /// </returns>
        public int active()
        {
            int ret;
    
            ret = super();
    
			// set parms for range field and value
            sysListPanel.parmRelationRangeField(fieldNum(SSIVendCategoryValueTable, Vendor));
            sysListPanel.parmRelationRangeValue(ssiVendCategoryValueTableRec.Vendor);
            sysListPanel.fill();

            return ret;
        }

    }

Tab page method allowPageDeactivate

The last piece of coding on the form is to add some logic to the allowPageDeactivate of the tab page control. This will handle any updates that are needed based on changes made to the list panel.

[Control("TabPage")]
    class vendCategoryValue
    {
        /// <summary>
        /// saves any changes made to record values
        /// </summary>
        /// <returns>
	 /// boolean
	 /// </returns>      
        public boolean allowPageDeactivate()
        {
            boolean ret;
    
            ret = super();
    
			// create new record if one doesn't already exists
            if (!SSIVendCategoryValueTable.RecId)
            {
                if (SSIVendCategoryValueTable_ds.validateWrite())
                {
                    SSIVendCategoryValueTable_ds.write();
                }
                else
                {
                    return false;
                }
            }

            return ret;
        }

That is all the coding that is needed for this functionality. The List panel will handle adding/removing any records from the tables. After all of this, you get something like the below.

Creating a list panel for a field lookup

When you click the drop down of the new vendor attribute field the lookup form appears. You can use the left/right arrows to add/remove values. The selected values are the records that are stored in the new table created in the prerequisites. It will store the value and the vendor. The values listed in the Available are from the table of the new EDT.

What’s New for Developers in Dynamics 365 for Finance and Operations? – Two-day Training

$
0
0

Are you a developer experienced in Dynamics AX 2009 and Dynamics AX 2012, but you need to level up your knowledge and skills for the newest product release? If so, we’ve created a course just for you! Stoneridge Software is offering a new training course, “What’s New in Dynamics 365 for Finance and Operations.”

“What’s New for Developers in Dynamics 365 for Finance and Operations” is a two-day class held online from 8:30 am – 4:30 p.m. with a lunch break. This training will provide students with an overview of the differences in development for those who have been working in Dynamics AX 2009 or AX 2012 and are moving to Dynamics 365 for Finance and Operations. It will cover architectural and development features and the tools available in the development environment. This workshop covers the essentials of doing development including creating tables, classes, forms, and reports. All students will have access to an environment for labs.

Register for training for Developers in Finance and Operations here.

What’s New for Developers in D365 for Finance and Operations Course Outline:

Visual Studio Overview

  • Projects
  • Solution Explorer
  • Working with Projects
  • References
  • Debugging

Architecture

  • IIS
  • Models
  • VS Project types
  • ModelUtil
  • Deployment Packages
  • Export/Importing Code
  • AOT

Tables and UI

  • Changes to Base Enums
  • Changes to Tables
  • Changes to Forms
  • Tiles
  • Menus
  • Workspaces
  • Labels

Changes in X++

  • Refresh of debugging
  • New base data typer
  • New look of boxes/dialog
  • New look of Infolog
  • Cross-company support
  • Working with files

Changes to Security

  • Data Entity Permissions
  • Direct Access/Field Level Permissions
  • Form Control Overrides

Data Entities

SSRS Reports

Register for Developer Training

Dynamics 365 for Finance and Operations: More Than One Form Was Opened at Once for the Lookup Control

$
0
0

In Dynamics 365 for Finance and Operations, when subscribing to a lookup event to modify an existing lookup on a form control, you must remove the super call to the existing lookup. Otherwise, when clicking on the control a message will display stating, “More than one form was opened at once for the lookup control.” An example of the message is shown in the upper right corner of the image below.

Multiple Forms in lookup control

The following steps can be utilized in the lookup event to cancel the super call of the original lookup:

  1. Declare a new variable of type FormControlCancelableSuperEventArgs.
  2. Initialize the new variable with the current FormControlEventArgs parameter ‘e’ and cast it as type FormControlCancelableSuperEventArgs.
  3. Finally, use the new variable and call the CancelSuperCall() method.

Below is an X++ example of subscribing to a lookup event and canceling the super call.

[FormControlEventHandler(formControlStr(VendCertification, StateId), FormControlEventType::Lookup)]
    public static void StateId_OnLookup(FormControl sender, FormControlEventArgs e)
    {
        // Declare and initialize new variable.
        FormControlCancelableSuperEventArgs formControlCancelSuper = e as FormControlCancelableSuperEventArgs;

        //Custom lookup code can go here.

        // Cancel the super call of lookup control.
        formControlCancelSuper.CancelSuperCall();
    }

 


UI Builder Class Not Using the Same Contract as Controller and DP Classes in Dynamics AX 2012

$
0
0

The other day I had to convert a custom query-based SSRS report within Dynamics AX 2012 into a regular report so that we could run the report from a different form (ProdTable & ProdTableListPage) and have certain values auto-populate the query prompt. Normally something like this would be easy to implement, however, I ran into some issues when making the modifications.

I created the data provider, Contract and Controller classes, and the dialog values were not changing. I ended up building a UI Builder class as well to counteract this issue. I had the logic to pre-populate the contract in the controller class by using the record that was highlighted, and I verified that the values were being pulled into the contract class as desired. I then stumbled across the issue of the UI Builder class was not using the same contract instance as the Controller & Data Provider classes. This was resulting in the values not populating the prompt and was not being passed to the Data Provider class. What I wound up having to do is to move my logic into the UI Builder class. Below I have provided the code I created in order to utilize this.

Controller main method:

public static void main(Args _args)
{
    SSI_DemoController controller = new SSI_DemoController();
    SSI_DemoContract contract = new SSI_DemoContract();

    controller.parmReportName(ssrsReportStr(SSI_DemoReport, Report));
    controller.parmArgs(_args);
    controller.parmShowDialog(true);
    controller.parmShowReportViewerParameters(false);

    controller.startOperation();
}

The rest of the logic had to be put into the UI Builder class, specifically the build method.

public void build()
{
    DialogField dlgItem;
    Args args;
    ProdTable prodTable;
    SRSPrintDestinationSettings printSettings;
    controllerDlg = this.controller();
    contract = this.dataContractObject();
    args = controllerDlg.parmArgs();

    controllerDlg.parmReportContract().parmRdpContract(contract);

    if(args.record() && args.record().TableId == tableNum(ProdTable))
    {
        prodTable = args.record();
        contract.parmItemId(prodTable.ItemId);
        contract.parmNumberOfCopies(prodTable.QtyCalc);
    }

    printSettings = controllerDlg.parmReportContract().parmPrintSettings();
    printSettings.printMediumType(SRSPrintMediumType::Printer);
    if(contract.parmNumberOfCopies() != 0)
    {
        printSettings.overridePageSettings(true);
        printSettings.overridePrintContractSettings(true);
        printSettings.numberOfCopies(contract.parmNumberOfCopies());
    }

    dlgItem = this.addDialogField(methodStr(SSI_DemoContract,parmItemId),contract);

    dlgItem = this.bindInfo().getDialogField(contract,methodStr(SSI_DemoContract,parmItemId));
}

This code was able to solve the issue I was having and should help you if you’re facing the same problems. Learn more tips for Dynamics AX 2012 by subscribing to our blog. If you have any questions in the meantime, please reach out to the experts at Stoneridge Software.

Updating the Next Rec ID Sequence in Dynamics AX

$
0
0
Recently I had to create database records outside of Dynamics AX. I used SQL to move some records from ISV tables to new standard tables within AX. There was a ton of data, so it was much faster to insert these records using SQL. Initially, I overlooked one important factor. When I created these records […]

X++ Select Statements That Look More Like SQL

$
0
0
As I’ve progressed as an AX developer, I’ve had to lean on many of the skills that I had from a former job as a C# developer where I used a lot of SQL queries. Working with data in X++ is similar until you try to write it like it would be written in SQL. […]

Using the new Chain of Command feature in X++

$
0
0
Recently a new feature for X++ developers was announced by Michael Fruergaard Pontoppidan (MFP) called Chain of Command. I knew I would want to try it out as soon as I had some time and it is pretty slick. This post will show it in action with a simple example in Microsoft Dynamics 365 Enterprise […]

Working With Kernel Based Classes and AOT Based Tables in Dynamics AX

$
0
0
Thinking in the Abstract If you have seen some of my blog articles before, you may have noticed that I look at automating documentation from time to time. This article will expand on the concept a bit, and use different components of Dynamics AX to accomplish or demonstrate some of the more abstract ways to […]

Project Committed Cost Not Updating After Changes to PO in Dynamics AX

$
0
0
If you are running Dynamics AX 2012 and are doing work within the Project module you might have noticed an issue around committed costs on projects. In this example, we are looking at how committed costs work with Purchase Orders in Dynamics AX. I’m going to assume you have a project setup along with a […]

How to Use the modelutil.exe to Delete a Model Name in Dynamics 365 for Operations

$
0
0
While getting introduced to development in Dynamics 365 for Finance and Operations, I found myself in a situation of adding/removing a model. There is a helpful tool we can use called “modleutil.exe”. This executable can be levied to accomplish a multitude of possibilities such as, import, delete, replace, and export. In order to use the […]

Creating a List Panel for a Field Lookup in Dynamics AX

$
0
0
I recently had a scenario where we had to create a new vendor attribute that could have one or more values assigned to a vendor. The requirement wanted a drop-down field that opened a form and showed which values had been selected and which ones are still available. The lookup form should also allow the […]

What’s New for Developers in Dynamics 365 for Finance and Operations? – Two-day Training

$
0
0
Are you a developer experienced in Dynamics AX 2009 and Dynamics AX 2012, but you need to level up your knowledge and skills for the newest product release? If so, we’ve created a course just for you! Stoneridge Software is offering a new training course, “What’s New in Dynamics 365 for Finance and Operations.” “What’s […]

Dynamics 365 for Finance and Operations: More Than One Form Was Opened at Once for the Lookup Control

$
0
0
In Dynamics 365 for Finance and Operations, when subscribing to a lookup event to modify an existing lookup on a form control, you must remove the super call to the existing lookup. Otherwise, when clicking on the control a message will display stating, “More than one form was opened at once for the lookup control.” […]

UI Builder Class Not Using the Same Contract as Controller and DP Classes in Dynamics AX 2012

$
0
0
The other day I had to convert a custom query-based SSRS report within Dynamics AX 2012 into a regular report so that we could run the report from a different form (ProdTable & ProdTableListPage) and have certain values auto-populate the query prompt. Normally something like this would be easy to implement, however, I ran into […]

Extension Model: Creating a Static Table Method in Dynamics 365 for Operations

Viewing all 71 articles
Browse latest View live