Monday, November 3, 2014

Layer Configuration In AX 2012

Changing Layer in Dynamics AX 2012:

1.      Click Start, point to Administrative Tools, and then click Microsoft Dynamics AX 2012 Configuration. The Microsoft Dynamics AX Configuration Utility opens.

In the Microsoft Dynamics AX Configuration Utility, click Manage, and then click Create configuration. The Create Configuration window opens

In the Configuration name field, enter a name for the configuration, and then click OK. The Create Configuration window closes
On the Developer tab, in the Application object layer to open field, select a new layer from the drop-down list.
On the Developer tab, in the Application object layer to open field, select a new layer from the drop-down list.
 
 
In the Development license code field type the license code and  confirm license field also give the same
 
Click Apply and  Click OK to save the configuration. The Microsoft Dynamics AX Configuration Utility window closes.
Close and restart the client in the new layer.

Specific user problem in ax 2009 or 2012.

When ever we face a problem for a specific user in AX 2009 or 2012. We have to delete *.auc files then the problem may resolve.

I  am going to mention how to delete the files kindly follow below 3 points and check.

1. Stop AOS.
2. Delete the *.auc files from users\\Appdata\ folder
3. Restart AOS.

Differences between MorphX and Intellimorph


MorphX 
MorphX is the Microsoft Dynamics AX IDE( Integrated Development Environment) which includes:
 - Data Dictionary
 - Tools for creating menus, forms and reports for Windows- and Web clients
 - Compiler and debugger for the object oriented programming language X++
 - Version control system
 - Label (multi language text) systems  :
IntelliMorph 
IntelliMorph is the Runtime Environment embedded in Microsoft Dynamics AX, that draws menus, forms, and reports for Windows- and Web-clients with the correct contents, size, and layout according to:
 - The language your texts are displayed in.
 - What features you can access.
 - How wide you want the fields on your installation.
 - The formats you are using for dates and numbers.

Thursday, March 20, 2014

Managing integration ports AX 2012

What are Integration ports?

Integrations ports are basically the inbound or outbound ports through which external applications can communicate with Dynamics AOS via AIF (WCF).

The exchange of data between External/Internal application is divided into:
1.      InBound Exchange
a.     Both Basic and Enhanced Integration ports can be used.
b.     Basically to Receive data and create in Ax

2.     OutBound Exchange
a.     Only Enhanced Integration ports can be used.
b.     To Send data to ext. applications
c.      To Send data to ext. applications in response to their Requests
 
How to: Create a Basic Inbound Integration Port [AX 2012]
Basic port is used to test the operation of a custom service that does not require any data processing or exposure to the Internet.
Only a developer can create a new basic integration port


To create a basic inbound port
 
  1. Open the Application Object Tree (AOT).
  2. Right-click the Service Groups node, and then click New Service Group.
  3. Right-click the new service group, and then click Properties. Set the Name property to TestBasicPortServiceGroup. Click Save.
  4. Right-click TestBasicPortServiceGroup, and then click Open New Window. Drag one of the custom services from the Services node onto TestBasicPortServiceGroup.
  5. Right-click TestBasicPortServiceGroup, and then click Save.


  6. Right-click TestBasicPortServiceGroup, and then click Deploy Service Group.

        
  7. After the service group is successfully deployed, a confirmation message appears in the Infolog. And the TestBasicPortServiceGroup port is appended to the Port Names list as a port of the Basic type.

        
  8. To view the basic port you have created, open the Inbound ports form. Click System administration > Setup > Services and Application Integration Framework >Inbound ports.
    The TestBasicPortServiceGroup port appears in the Port Names list as a port of the Basic type.
Important: To start this service every time that the AOS is restarted, set the AutoDeploy property for the service group to Yes.

How to manage the Enhanced integration port:
#1: To create an enhanced integration port, follow these steps.
1.      To create an inbound integration port, open the Inbound ports form. Click System administration > Setup > Services and Application Integration Framework > Inbound ports.
–or–
To create an outbound integration port, open the Outbound ports form. 
Click System administration > Setup > Services and Application Integration Framework > Outbound ports.

2.     Click New.


3.     Enter a name and description for the new integration port. The name of a port must begin with a letter and can contain only alphanumeric characters.

4.     Configure the integration port
Click service operations – to select Service operations which you want to perform using this Enchanced port.
Close Select service operations form.

5.     Or just click Close to save the default configuration and you can modify the configuration later.

6.     Click button Activate

Important: 
If you activate or deactivate an integration port, all integration ports on that particular instance of AOS are reactivated. 
Do not click the Deactivate/Activate button while integration ports are processing messages.

#2: To Edit or delete an enhanced integration port, follow these steps:

To change the settings for an existing enhanced integration port, or to delete the port, you must first deactivate the port.
1.      Identify and select the particular Port name field you want to change or delete.

2.     Click Deactivate to deactivate the port.

3.     Change the configuration settings.
–or–
Click Delete to delete the port.

4.     Click Activate to reactivate the integration port.

#3: Configure addresses for Enhanced Integration ports:
Enhanced integration ports use adapters to enable Microsoft Dynamics AX to communicate by using various transport protocols.
The addresses of integration ports are defined by the adapters that you select and the Uniform Resource Identifiers (URIs) of the adapters.
Inbound integration ports have an inbound address that is used for inbound messages, and they can also have a response address that is used for outbound messages.
Outbound integration ports have only an outbound address that is used for outbound messages.
 
How to Register Adapaters:
An adapter must be registered before it can be used. Adapters that are included with Microsoft Dynamics AX are automatically registered during installation.
Whenever a new adapter is added to the (AOT), you must register the adapter to make it available in the configuration forms for enhanced integration ports.
To register adapters, follow these steps:
1.      Click System administration > Setup > Checklists > Initialization checklist.

2.     Expand the Initialize system node.

3.     Click Set up Application Integration Framework. By doing so, Adapters, basic ports, and services are registered. This operation can take some time to be completed.
 
How to select Adapaters:
After adapters have been registered, you must select the adapters that you want to use for integration.
In the Address group or the Response address group, click the arrow in the Adapter field, and then select an adapter in the list.
The list by default consists of:
1.      File system adapter – Receive or Send
2.     HTTP – Send and receive
3.     ISABEL SEPA credit transfer – Receive or Send
4.     MSMQ – Receive or Send
5.     NetTcp – Send and receive
You can select the appropriate adapter for your connection when you configure an enhanced integration port.

How to Specify URIs
Before you can configure an adapter, you must specify its URI. The format of the URI varies, depending on the type of adapter that you selected:
1.      For File system adapter and:
a.     Address is an inbound address then the URI is the file system path of the directory where the port retrieves documents.
b.     And if the address is an outbound/response address, the URI is the file system path of the directory where the port saves documents. 
To select a directory, click the arrow in the URI field, and then browse to a folder.
Notes: 
Make sure that the service account for Application Object Server (AOS) has the appropriate read or write permissions for the directory. When you submit multiple documents to a port that uses the file system adapter, the documents are processed in order based on the file names. (Workaround if needed, is to use file names that include a sequencing scheme, such as "PO_0001" and "PO_0002")

2.     For NetTcp adapter, the URI is automatically provided by Microsoft Dynamics AX, based on the port name. You can view the URI after you save the port configuration.

3.     For MSMQ adapter, the URI is based on the queue that you select. To select a queue, click the arrow in the URI field, and then select a queue in the list. 
The server must be configured to provide Message Queuing services, and queues must be defined before they can be used by the integration port.

4.     For HTTP adapter type is HTTP, the URI is the Internet address of a website that you added by using the Web sites form. To select a website, click the arrow in the URI field. Then, in the Select Web site form, click the arrow in the Web site field, and then select a website in the list.
 

How to Configure adapters:
After you specify the URI of the adapter that you selected, you can configure the adapter.
In the Address group or the Response address group, click Configure. In Microsoft Dynamics AX 2012 R2, for adapter types other than NetTcp, to make the Configure AOS button visible you must save the port first.
One of the following configuration forms opens:
1.      For the file system adapter, the File system adapter configuration form opens. The Microsoft Dynamics AX user account that is specified should have required rights. For example, User Account Control (UAC) is enabled in Windows, and files are created by an administrator account. For these files, the Owner attribute in the file properties is set to the Windows Administrators group. Similarly, for files that are created from a process that runs on a network service, the owner is set to NT AUTHORITY\NETWORK SERVICE.
2.     For NetTcp, HTTP, and MSMQ adapters which are based on Windows Communication Foundation (WCF), the WCF configuration form opens.
The WCF configuration form contains the WCF Configuration Editor tool, SvcConfigEditor.exe, if the tool is installed. This tool is installed as a component of some versions of the Windows SDK and by Microsoft Visual Studio 2010. This tool provides a graphical user interface (GUI) that you can use to create and modify configuration settings for WCF services. 
If the WCF Configuration Editor tool is not installed, the WCF configuration file opens in Notepad. You can change the WCF configuration information by modifying the XML code in Notepad. Then save the file.

Generation;The given key was not present in the dictionary

While working, I encountered this error. The error is mentioned in the image below:
CIL Generator Found Errors and Could not save the assembly
And the compilation log had the following error:
The given key was not present in the dictionary
I was able to solve the error by carrying out the outlined steps:
1.Restart AOS Service
2.Generate Full CIL
In case, you do not have enough time for the Full compilation, go the error log and recompile the objects mentioned in the error message.

Creating a Customer Form at Run Time in X++

The job “CustomerForm” creates a customer form at run time in x++. In the form, I have used two datasources “CustTable” and “DirPartyTable”. I have also shown how to add menuitemfunctions in a form through X++.
Here is the code in X++:
public static void CustomerForm(Args _args)
{
//Initialization
DictTable dictTable;
DictTable dictTable1;
Form form;
FormBuildDesign design;
FormBuildDataSource formBuildDataSource;
FormBuildDataSource formBuildDataSource1;
FormBuildActionPaneControl actionPane;
FormBuildActionPaneTabControl actionPaneTab;
FormBuildButtonGroupControl buttonGroup1;
FormBuildButtonGroupControl buttonGroup2;
FormBuildCommandButtonControl CommandNew;
FormBuildCommandButtonControl CommandDelete;
FormBuildMenuButtonControl CustomerButton;
FormBuildFunctionButtonControl NewCustomerButton;
FormBuildFunctionButtonControl ForecastButton;
FormBuildGroupControl Grp;
FormBuildGridControl grid;
FormBuildGroupControl grpBody;
Args args;
FormRun formRun;
#task
//Adding DataSources
dictTable1 = new DictTable(tableNum(CustTable));
dictTable = new DictTable(tableNum(DirPartyTable));
form = new Form();
form.name(“Customer Overview”);
formBuildDataSource = form.addDataSource(dictTable.name());
formBuildDataSource.table(dictTable.id());
formBuildDataSource1 = form.addDataSource(dictTable1.name());
formBuildDataSource1.table(dictTable1.id());
//Building Form Design
design = form.addDesign(‘Design’);
design.caption(“Overview”);
design.style(FormStyle::SimpleList);
design.titleDatasource(formBuildDataSource.id());
//Adding Action Pane and Buttons
actionPane = design.addControl(
FormControlType::ActionPane, ‘ActionPane’);
actionPane.style(ActionPaneStyle::Strip);
actionPaneTab = actionPane.addControl(FormControlType::ActionPaneTab, ‘ActionPaneTab’);
buttonGroup1 = actionPaneTab.addControl(FormControlType::ButtonGroup, ‘NewDeleteGroup’);
buttonGroup2 = actionPaneTab.addControl(FormControlType::ButtonGroup, ‘ButtonGroup’);
CommandNew = buttonGroup1.addControl(FormControlType::CommandButton, ‘NewButton’);
CommandNew.buttonDisplay(FormButtonDisplay::TextAndImageLeft);
CommandNew.normalImage(’11045′);
CommandNew.imageLocation(SysImageLocation::EmbeddedResource);
CommandNew.primary(NoYes::Yes);
CommandNew.command(#taskNew);
CommandDelete = buttonGroup1.addControl(FormControlType::CommandButton, ‘NewButton’);
CommandDelete.text(“Delete”);
CommandDelete.buttonDisplay(FormButtonDisplay::TextAndImageLeft);
CommandDelete.normalImage(’10121′);
CommandDelete.imageLocation(SysImageLocation::EmbeddedResource);
CommandDelete.saveRecord(NoYes::Yes);
CommandDelete.primary(NoYes::Yes);
CommandDelete.command(#taskDeleteRecord);
CustomerButton = buttonGroup2.addControl(FormControlType::MenuButton, ‘CustomerquickCreate’);
CustomerButton.helpText(“Create New Customer”);
CustomerButton.text(“Customer”);
NewCustomerButton = CustomerButton.addControl(FormControlType::MenuFunctionButton, ‘CustomerquickCreate’);
NewCustomerButton.text(‘New’);
NewCustomerButton.saveRecord(NoYes::No);
NewCustomerButton.dataSource(formBuildDataSource.id());
NewCustomerButton.menuItemName(menuitemDisplayStr(CustomerquickCreate));
ForecastButton = buttonGroup2.addControl(FormControlType::MenuFunctionButton, ‘SalesForecast’);
ForecastButton.text(‘Forecast’);
ForecastButton.saveRecord(NoYes::No);
ForecastButton.menuItemName(menuitemDisplayStr(ForecastSalesGroup));
//Body
grpBody = design.addControl(FormControlType::Group, ‘Body’);
grpBody.heightMode(FormHeight::ColumnHeight);
grpBody.columnspace(0);
grpBody.style(GroupStyle::BorderlessGridContainer);
grid = grpBody.addControl(FormControlType::Grid, “Grid”);
grid.dataSource(formBuildDataSource.name());
grid.widthMode(FormWidth::ColumnWidth);
grid.heightMode(FormHeight::ColumnHeight);
grid.addDataField(formBuildDataSource.id(), fieldNum(DirPartyTable,Name));
grid.addDataField(formBuildDataSource1.id(), fieldNum(CustTable,AccountNum));
grid.addDataField(formBuildDataSource.id(), fieldNum(DirPartyTable,LanguageId));
Grp = design.addControl(FormControlType::Group, ‘Group’);
ForecastButton = Grp.addControl(FormControlType::MenuFunctionButton, ‘SalesForecast’);
ForecastButton.text(‘Forecast’);
ForecastButton.menuItemName(menuitemDisplayStr(ForecastSalesGroup));
args = new Args();
args.object(form);

formRun = classFactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.detach();
}

The SysOperation Framework Overview


Previously, the Runbase framework was being used to add the functionality that required batch processing. The Runbase framework has been replaced by the SysOperation framework, formerly known as Business Operation Framework. The Sysoperation framework creates a user interface which can be integrated with the batch server for batch processing.
The SysOperation framework can be used to implement operations that can scale to multiple processors by batch processing. It can also be implemented to prompt the user for an input. The batch processing feature can be used to control the time and duration of the operations which require more processing time. The framework also has support for queries, routing tasks and pack and unpack for parameter serialization.
The SysOperation framework basically enhances the performance of operations by explicitly scheduling their execution. Through the framework, the operations can be executed on user interaction or by scheduling them through the batch server.
The framework is an implementation of the MVC design pattern. The structure of the framework is defined below:
Model:
• Members
• Pack/UnPack
• Data contract
View:
• Dialog
Controller:
• Process
• User Prompt
• Run


This post was a short introduction to the SysOperation Framework. I will be writing about the comparison of Runbase framework and SysOperation framework in my next post. Tune in again to the blog for more info regarding the SysOperation framework.

Dynamics AX 2012 Data Import using X++


Microsoft Dynamics AX 2012 Xpp –
Sales Orders Import
 
Purpose: The purpose of this document is to illustrate how to write a required minimum X++ code in Microsoft Dynamics AX 2012 in order to import Sales orders.
 
Challenge: Data model changes in Microsoft Dynamics AX 2012 related to high normalization and introduction of surrogate keys made some imports more complex. However the structure of tables comprising Sales order header/lines didn't change. Please note that after you import Sales orders you may need to perform full/partial Physical and/or Financial update if required (for example, for Purchase orders already in execution).
 
Solution: Appropriate tables buffers (SalesTable, SalesLine) will be used when writing X++ code in Microsoft Dynamics AX 2012 in order to import Sales orders. Alternatively AxBC classes may be used instead of table buffers.
 
Data Model:
 
Table Name
Table Description
SalesTable
The SalesTable table contains all sales order headers regardless of whether they have been posted.
SalesLine
The SalesLine table contains all sales order lines regardless of whether they have been posted.
InventDim
The InventDim table contains values for inventory dimensions.
 
Data Model Diagram:
<![if !vml]><![endif]>
 
Development:
 
ttsBegin: Use ttsBegin to start a transaction.
 
clear: The clear method clears the contents of the record.
 
initValue: The initValue method initializes the fields of the record.
initFrom*: The initFrom* methods usually populate the fields of the child record based on the fields on the parent record. Example is initFromSalesTable method on SalesLine table.
 
validateWrite: The validateWrite method checks whether the record can be written.
write: The write method writes the record to the database.
 
insert: The insert method inserts the record into the database.
doInsert: The doInsert method inserts the record into the database. Calling doInsert ensures that any X++ code written in the insert method of the record is not executed. Calling insert always executes the X++ code written in theinsert method of the record.
 
ttsCommit: Use ttsCommit to commit a transaction.
 
Source code:
static void SalesOrdersXppImport(Args _args)
{
    #define.Customer("US-001")
    #define.DeliveryDate("1/1/2014")
    #define.ItemId("M0001")
    #define.Qty(10)
    #define.Unit("ea")
 
    SalesTable      salesTable;
    SalesLine       salesLine;
    InventDim       inventDim;
 
    try
    {
        ttsbegin;
 
        //Order header
        salesTable.clear();
        salesTable.initValue(SalesType::Sales);
        salesTable.SalesId = NumberSeq::newGetNum(SalesParameters::numRefSalesId()).num();
        salesTable.DeliveryDate = str2Date(#DeliveryDate, 213);
        salesTable.CustAccount = #Customer;
        salesTable.initFromCustTable();       
 
        if (salesTable.validateWrite())
        {
            salesTable.insert();
 
            //Order line
            inventDim.clear();
            inventDim.InventSiteId = "1";
            inventDim.InventLocationId = "12";
 
            salesLine.clear();
            salesLine.initValue(salesTable.SalesType);
            salesLine.initFromSalesTable(salesTable);
            salesLine.ItemId = #ItemId;
            salesLine.initFromInventTable(InventTable::find(#ItemId));
 
            salesLine.InventDimId = InventDim::findOrCreate(inventDim).inventDimId;
            salesLine.SalesQty = #Qty;
            salesLine.RemainSalesPhysical = salesLine.SalesQty;
            salesLine.SalesUnit = #Unit;
            salesLine.QtyOrdered = salesLine.calcQtyOrdered();
            salesLine.RemainInventPhysical = salesLine.QtyOrdered;
 
            salesLine.setPriceDisc(InventDim::find(salesLine.InventDimId));
 
            if (salesLine.validateWrite())
            {
                salesLine.insert();
            }
            else
                throw error("Order line");
        }
        else
            throw error("Order header");
 
        ttscommit;
    }
    catch
    {
        error("Error!");
        return;
    }
 
    info("Done!");
}
 

X++ code to filter a lookup field on form in ax2012

lookup for custaccount field, when open the custtable (custaccount field)  form

public void lookup()
{
Query query = new Query();
QueryBuildDataSource qbds_CustTable;
SysTableLookup sysTableLookup;
QueryBuildRange qbr;
//super();
sysTableLookup = SysTableLookup::newParameters(tablenum(CustTable), this);
qbds_CustTable = query.addDataSource(tableNum(CustTable));
sysTableLookup.addLookupfield(fieldnum(CustTable, AccountNum), true);
sysTableLookup.addLookupfield(fieldnum(CustTable, CustGroup),true);
qbr = qbds_CustTable.addRange(fieldNum(CustTable,CustGroup));
qbr.value(‘ENDUSER’);
sysTableLookup.parmUseLookupValue(false);
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}