Loncar Technologies has created an amazing product to improve development and analysis en AX (AX4, AX2009 and now AX2012). Take a look at http://www.loncartechnologies.com.
Also, get some free stuff: LC AOT Browser (browse the AOT filtered by a layer) and LC Project search (search for an object in all projects nodes).
Enjoy it !!!
C# and AX Development
Development and other stuff
Monday, May 02, 2011
Friday, July 17, 2009
Updating the caller Form/DataSource
If we need to notify events to the caller form we can try this pattern:
In the child form, make a method named updateCaller and invoke it when you want to notify the parent:
Implement the handling method in the parent form:
Or if you prefer, in the DataSource:
Invoking it from a simple button inside the child form:
See a pratical sample in the form MarkupTrans (DataSource -> method write).
In the child form, make a method named updateCaller and invoke it when you want to notify the parent:
void updateCaller() { Common common; Object dataSource; Object caller; ; //----------------------------------- //We are notifying using the dataSource common = element.args().record(); if (common && common.isFormDataSource() && formDataSourceHasMethod(common.dataSource(), identifierstr(SomethingWasHappend))) { dataSource = common.dataSource(); dataSource.SomethingWasHappend(); } //----------------------------------- //----------------------------------- //We are notifying using the form caller = element.args().caller(); if (caller && classidget(caller) == classnum(SysSetupFormRun) && formHasMethod(caller, identifierstr(SomethingWasHappend))) { caller.SomethingWasHappend(); } //----------------------------------- }
Implement the handling method in the parent form:
void SomethingWasHappend() { ; info("Something was happend (Form)"); }
Or if you prefer, in the DataSource:
void SomethingWasHappend() { ; info("Something was happend (DataSource)"); }
Invoking it from a simple button inside the child form:
void clicked()
{
super();
element.updateCaller();
}See a pratical sample in the form MarkupTrans (DataSource -> method write).
Saturday, June 27, 2009
How to delete AOT nodes by code (UtilIdElements solution)
In my old post: How to delete AOT objects (AX/Axapta), I have used the TreeNode class. There is another useful method by using the UtilIdElements system table described in the following links:
- MS KB 913530 (CustomerSource)
- forum topic: microsoft.public.axapta.programming - Currupt records in UtilIdElement and UtilElements
Warning: Serious problems might occur if you modify the UtilIdElements table using this or another method. Modify system tables at your own risk.
The code:
- MS KB 913530 (CustomerSource)
- forum topic: microsoft.public.axapta.programming - Currupt records in UtilIdElement and UtilElements
Warning: Serious problems might occur if you modify the UtilIdElements table using this or another method. Modify system tables at your own risk.
The code:
static void Job1(Args _args) { UtilIdElements utilElement; ; ttsbegin; select utilElement where utilElement.name == 'myElementName' && utilElement.utilLevel == utilEntryLevel::cus // any layer && utilElement.recordType == utilElementType::Table; // object type if (utilelement) { utilElement.delete(); ttscommit; info('Record should be deleted now.'); } else { ttsAbort; info('Could not delete record, or it was not found.'); } }
AOS crashed due corrupted node in the AOT
Warning: this post is only informative, do not try to replicate the problem described here in a production environment. !!!!
The problem:
The problem occurred when we created a 'View' with one circular reference. After that, every time we tried to click over "Data Dictionary\Tables" or "Data Dictionary\Views", the AOS crashes.
How to reproduce the problem:
Warning: this post is only informative, do not try to replicate the problem described here in a production environment. !!!!
0. Make a backup. Also, make a copy of the AxCus.AOD file.
1. Create a simple view (ex. View1).
2. Add a new DataSource manually. Then, open DataSource's properties dialog and specify in the table field the name of the view you have created (ex. View1).
3. STOP at this point if you dont want to crash the AOS !!!.
4. Expand the DataSource node. Drag the field CreatedBy to the view's fields. It will create the CreatedBy1 field.
5. Save it if you are sure you want to continue. After this action, your AOS will crash. (oops !)
You can try to recover the error by deleting the corrupted node (ex. View1 or CreatedBy1 field) using this method: How to delete AOT objects (AX/Axapta) or this other: How to delete AOT nodes by code (UtilIdElements solution). None of them will work!!!.
The solution:
After several tries, the only solution was open the AxCus.AOD file in a binary editor (Visual Studio is enough) and perform the next steps.
Warning: Serious problems might occur if you modify the AxCus.AOD file using this or another method. Modify system files at your own risk.
0. Make a backup. Also, make a copy of the AxCus.AOD file.
1. Stop the AOS and open the AxCus.AOD in a binary editor.
2. Locate the "CreatedBy1" field data (or your corrupted node's name). Normally, it should be near to the end of the file. (Look at pictures for details).
3. Change the reference data. It is above the field's name. Put the value FF FF (65,535) in the parent and field ids.
4. Save the file.
5. Delete the index file axapd.aoi.
6. Start the AOS again.
7. Delete the corrupted view.
Image with the corrupted node:

Image with the fixed node:

It is probable the corrupted node stays alive in the AOT, so you can try the following code to remove it:
The problem:
The problem occurred when we created a 'View' with one circular reference. After that, every time we tried to click over "Data Dictionary\Tables" or "Data Dictionary\Views", the AOS crashes.
How to reproduce the problem:
Warning: this post is only informative, do not try to replicate the problem described here in a production environment. !!!!
0. Make a backup. Also, make a copy of the AxCus.AOD file.
1. Create a simple view (ex. View1).
2. Add a new DataSource manually. Then, open DataSource's properties dialog and specify in the table field the name of the view you have created (ex. View1).
3. STOP at this point if you dont want to crash the AOS !!!.
4. Expand the DataSource node. Drag the field CreatedBy to the view's fields. It will create the CreatedBy1 field.
5. Save it if you are sure you want to continue. After this action, your AOS will crash. (oops !)
You can try to recover the error by deleting the corrupted node (ex. View1 or CreatedBy1 field) using this method: How to delete AOT objects (AX/Axapta) or this other: How to delete AOT nodes by code (UtilIdElements solution). None of them will work!!!.
The solution:
After several tries, the only solution was open the AxCus.AOD file in a binary editor (Visual Studio is enough) and perform the next steps.
Warning: Serious problems might occur if you modify the AxCus.AOD file using this or another method. Modify system files at your own risk.
0. Make a backup. Also, make a copy of the AxCus.AOD file.
1. Stop the AOS and open the AxCus.AOD in a binary editor.
2. Locate the "CreatedBy1" field data (or your corrupted node's name). Normally, it should be near to the end of the file. (Look at pictures for details).
3. Change the reference data. It is above the field's name. Put the value FF FF (65,535) in the parent and field ids.
4. Save the file.
5. Delete the index file axapd.aoi.
6. Start the AOS again.
7. Delete the corrupted view.
Image with the corrupted node:

Image with the fixed node:

It is probable the corrupted node stays alive in the AOT, so you can try the following code to remove it:
static void Job1(Args _args) { UtilIdElements utilElement; ; ttsbegin; select utilElement where utilElement.id == 65535; // Invalid ID we have writed in the AxCus.AOD file if (utilelement) { utilElement.delete(); ttscommit; info('Record should be deleted now.'); } else { ttsAbort; info('Could not delete record, or it was not found.'); } }
Tuesday, March 17, 2009
Posting a ledger journal
Here is the adapted example for posting a ledger journal line. Simply replace values between #s (#value#):
Note: you can expand to include more than one line. Enjoy!
static void ExampleLedgerJournal(Args _args) { LedgerJournalTable ledgerJournalTable; LedgerJournalTrans ledgerJournalTrans; LedgerJournalCheckPost ledgerJournalCheckPost; NumberSeq numberSeq; ; ttsbegin; // Journal name ledgerJournalTable.JournalName = "#JOURNALNAME#"; // ex. Daily, daytrans, etc. ledgerJournalTable.initFromLedgerJournalName(); ledgerJournalTable.Name = "#DESCRIPTION#"; // description for this journal ledgerJournalTable.insert(); // Voucher numberSeq = NumberSeq::newGetVoucherFromCode(LedgerJournalName::find(ledgerJournalTable.JournalName).VoucherSeries); ledgerJournalTrans.Voucher = numberSeq.voucher(); // Lines ledgerJournalTrans.JournalNum = ledgerJournalTable.JournalNum; ledgerJournalTrans.CurrencyCode = CompanyInfo::standardCurrency(); ledgerJournalTrans.ExchRate = Currency::exchRate(ledgerJournalTrans.CurrencyCode); ledgerJournalTrans.AccountNum = "#ACCOUNT#"; ledgerJournalTrans.AccountType = LedgerJournalACType::Ledger; ledgerJournalTrans.AmountCurDebit = #VALUE#; ledgerJournalTrans.TransDate = systemDateGet(); //Avoid the Today function ledgerJournalTrans.OffsetAccount = "#OFFSET ACCOUNT#"; ledgerJournalTrans.Txt = "#TXT#"; ledgerJournalTrans.insert(); //Posting the Journal ledgerJournalCheckPost = LedgerJournalCheckPost::newLedgerJournalTable(ledgerJournalTable, NoYes::Yes); ledgerJournalCheckPost.run(); ttscommit; }
Note: you can expand to include more than one line. Enjoy!
Friday, February 06, 2009
Delivering large strings through WCF
If you have trouble sending large strings through WCF (more than 8192 bytes), it is probable you need to configure the parameter ReaderQuotas.MaxStringContentLength (default value is 8192). This parameter should be configured in both sides (client and server) as needed.
Set this by code:
or modifying the config file:
Set this by code:
NetTcpBinding tcp = new NetTcpBinding();
tcp.ReaderQuotas.MaxStringContentLength = 65535;
or modifying the config file:
... <binding name="myTcpBinding"> <readerQuotas maxStringContentLength="65535" /> ... </binding> ...
Wednesday, January 14, 2009
MG Instant Messaging for AX (Freeware)
Based in MeetGate, I've developed this simple messaging system for use in DAX. This is not a fully Instant Messaging system yet, but provides a simple and efficient chat for improve co-workers communication, and the best part, is freeware.
The server includes only a small subset of MeetGate's features and was developed using .NET Framework 3.5 (WCF). I hope someday I could improve it with others important services like the "File Publication" for automatic distribution of files using the Presence Indicator.
You can use it for free under terms of The Microsoft Public License (Ms-PL).
Installation
Copy the server's files anywhere and install the windows service by running the command line: MGServerSvc /install. For uninstall it, simply run in the command line: MGServerSvc /uninstall.
The server's address can be configured by creating or editing the MGServerSvc.exe.config file as:
You need to copy the following files to the DAX client's directory, usually located in C:\Program Files\Microsoft Dynamics AX\40\Client\Bin:
MGControlAX.dll
MGLibrary.dll
MGClientLibrary.dll
For the Dynamics AX client, you need to install the ActiveX MGControlAX.dll. Dynamics AX cannot process events from managed components so the only way to notify events in DAX is by building an ActiveX control. In my case, I developed the MGControlAX.dll and before use it, you must register it as:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm MGControlAX.dll /tlb /codebase
NOTE: Remember the parameters: /tlb /codebase.
After that, you can import the .XPO project and edit the login method in the form MGToolbar. This form runs as a DAX toolbar so you can always access its buttons: login/logout, contacts and close.
If you press the button contacts and it will show you the list of available contacts (This version is NOT users limited). If you make double click over an online contact you can start chatting with him. All changes in any contact's status is notified (Online/Offline) and you can see the icon as green or red respectively.
Files for download:
Server's files
The XPO file
Client's files
The server includes only a small subset of MeetGate's features and was developed using .NET Framework 3.5 (WCF). I hope someday I could improve it with others important services like the "File Publication" for automatic distribution of files using the Presence Indicator.
You can use it for free under terms of The Microsoft Public License (Ms-PL).
InstallationCopy the server's files anywhere and install the windows service by running the command line: MGServerSvc /install. For uninstall it, simply run in the command line: MGServerSvc /uninstall.
The server's address can be configured by creating or editing the MGServerSvc.exe.config file as:
<configuration> <appSettings> <add key="BaseAddress" value="net.tcp://localhost:8000/MGServerService"/> </appSettings> </configuration>
You need to copy the following files to the DAX client's directory, usually located in C:\Program Files\Microsoft Dynamics AX\40\Client\Bin:
MGControlAX.dll
MGLibrary.dll
MGClientLibrary.dll
For the Dynamics AX client, you need to install the ActiveX MGControlAX.dll. Dynamics AX cannot process events from managed components so the only way to notify events in DAX is by building an ActiveX control. In my case, I developed the MGControlAX.dll and before use it, you must register it as:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm MGControlAX.dll /tlb /codebase
NOTE: Remember the parameters: /tlb /codebase.
After that, you can import the .XPO project and edit the login method in the form MGToolbar. This form runs as a DAX toolbar so you can always access its buttons: login/logout, contacts and close.
void Login() { UserId currentUserId = curuserid(); UserInfo userInfo; ; select firstonly userInfo where userInfo.id == currentUserId; if (userInfo.name != "") MGControlX.UserName(userInfo.name); else MGControlX.UserName(userInfo.Id); MGControlX.Domain(userInfo.networkDomain); MGControlX.BaseAddress("net.tcp://localhost:8000/MGServerService/MGServerService"); MGControlX.Login(); }
If you press the button contacts and it will show you the list of available contacts (This version is NOT users limited). If you make double click over an online contact you can start chatting with him. All changes in any contact's status is notified (Online/Offline) and you can see the icon as green or red respectively.
Files for download:
Server's files
The XPO file
Client's files
Monday, December 29, 2008
WCF interface for Dynamics AX
In DAX you must implement a lot of interfaces, some of them using ADO, AIF, WS, MSMQ, etc. I have developed my own interface using WCF (.NET Framework 3.5).
In this interface, I built two applications: the server that interacts with DAX by using the Business Connector and the client that is a standalone application that doesn't need ADSI and can run outside of the organization, for example, to send or receive data from partners automatically.

The example bellow includes the source code for Visual Studio 2008 and the DAX project (.xpo). In this project, I transport data from a local database (MyTable) to an owner table in DAX: WCFMyTable. Also, I can detect changes from any DAX table and send data to the client. For example: when any customer is added, I can replicate this data to legacy systems.

The DAX project includes the following elements:
WCFMyTable: this is a sample table for receive data from the client side.
WCFConnTest: this class is used to test the connection with DAX. The method getCustomer can be used for retrieve the first customer in the table CustTable.
WCFTask: is a class that encapsulates the access to any table we want to send to the client.
getRecord - returns a common record.
getRecordAxXml - returns the xml representation for the record this task is belong to.
MarkAsOK - update the task with a successful result when the client has processed it.
MarkAsFAILED - update the task as "failed" when the client has processed it and an error was raised. Tasks with errors are not removed from the table for debugging purposes.
WCFSender: this is the class that can be used for create a task for deliver to the client. You must override the update, insert and delete methods in the table you want to send. Here are the insert and update methods from the Dimensions table:
WCFTasks: this table store all tasks pending for deliver to the client. The table only store the reference to the record by tableId and recId.
WCFInterface: this is the main class that is used for read tasks from server (method getNextTask) and send data to server (method ProcessTask).
getNextTask: with this method we can get the next task for processing in the client side and at the same time, we can update the previous one. By using the Company and previousCompany parameters, we can read tasks from several companies.
ProcessTask: this is the method called when we want to send data back to DAX. We can also send multi-company data by specifying the Company parameter.
Here are the files for download:
Visual Studio 2008 project (AXInterface.zip)
The DAX project: WCFInterface.xpo
MyTable.sql definition
License: The Microsoft Public License (Ms-PL)
In this interface, I built two applications: the server that interacts with DAX by using the Business Connector and the client that is a standalone application that doesn't need ADSI and can run outside of the organization, for example, to send or receive data from partners automatically.

The example bellow includes the source code for Visual Studio 2008 and the DAX project (.xpo). In this project, I transport data from a local database (MyTable) to an owner table in DAX: WCFMyTable. Also, I can detect changes from any DAX table and send data to the client. For example: when any customer is added, I can replicate this data to legacy systems.

The DAX project includes the following elements:
WCFMyTable: this is a sample table for receive data from the client side.
WCFConnTest: this class is used to test the connection with DAX. The method getCustomer can be used for retrieve the first customer in the table CustTable.
WCFTask: is a class that encapsulates the access to any table we want to send to the client.
getRecord - returns a common record.
getRecordAxXml - returns the xml representation for the record this task is belong to.
MarkAsOK - update the task with a successful result when the client has processed it.
MarkAsFAILED - update the task as "failed" when the client has processed it and an error was raised. Tasks with errors are not removed from the table for debugging purposes.
WCFSender: this is the class that can be used for create a task for deliver to the client. You must override the update, insert and delete methods in the table you want to send. Here are the insert and update methods from the Dimensions table:
public void insert() { super(); // Send this task WCFSender::SendThisRecord(this); // End }
public void update() { DimensionSetCombination dimensionSetCombination; ; ttsbegin; if (this.Closed != this.orig().Closed) { update_recordset dimensionSetCombination setting active = !this.Closed where dimensionSetCombination.Dimension[Dimensions::code2ArrayIdx(this.DimensionCode)] == this.Num; } super(); ttscommit; // Send this task WCFSender::SendThisRecord(this); // End }
WCFTasks: this table store all tasks pending for deliver to the client. The table only store the reference to the record by tableId and recId.
WCFInterface: this is the main class that is used for read tasks from server (method getNextTask) and send data to server (method ProcessTask).
getNextTask: with this method we can get the next task for processing in the client side and at the same time, we can update the previous one. By using the Company and previousCompany parameters, we can read tasks from several companies.
ProcessTask: this is the method called when we want to send data back to DAX. We can also send multi-company data by specifying the Company parameter.
Here are the files for download:
Visual Studio 2008 project (AXInterface.zip)
The DAX project: WCFInterface.xpo
MyTable.sql definition
License: The Microsoft Public License (Ms-PL)
Subscribe to:
Posts (Atom)